Sortuj i policz liczbę wystąpień linii

145

Mam plik Apachedziennika, access.logjak policzyć liczbę wystąpień linii w tym pliku? na przykład wynikiem cut -f 7 -d ' ' | cut -d '?' -f 1 | tr '[:upper:]' '[:lower:]'jest

a.php
b.php
a.php
c.php
d.php
b.php
a.php

wynik, który chcę to:

3 a.php
2 b.php
1 d.php # order doesn't matter
1 c.php 
Kokizzu
źródło
25
| sort | uniq -c
Costas
3
| LC_ALL=C sort | LC_ALL=C uniq -c
Stéphane Chazelas
ah, nigdy nie wiem, że to uniqmoże zrobić ...
Kokizzu
Czy masz przykład linii w dzienniku, ponieważ myślę, że można to zrobić za pomocą awk bez wszystkich rur.
jest w porządku, plik dziennika 8,1 GB jest przetwarzany w ciągu około 2 minut i jest już gotowy, nie jest już potrzebny: 3
Kokizzu

Odpowiedzi:

196
| sort | uniq -c

Jak stwierdzono w komentarzach.

Pipingowanie danych wyjściowych w sortporządkuje dane wyjściowe w kolejności alfabetycznej / numerycznej.

Jest to wymagane, ponieważ uniqpasuje tylko do powtarzających się linii, tj

a
b
a

Jeśli użyjesz uniqtego pliku tekstowego, zwróci on:

a
b
a

Jest tak, ponieważ dwa as są oddzielone znakiem b- nie są to kolejne wiersze. Jeśli jednak najpierw posortujesz dane w kolejności alfabetycznej, np

a
a
b

Następnie uniqusunie powtarzające się linie. -cOpcja uniqzlicza liczbę powtórzeń i zapewnia wyjście w postaci:

2 a
1 b

Bibliografia:

visudo
źródło
1
Witamy w systemach Unix i Linux :) Nie wahaj się dodać więcej szczegółów do swojej odpowiedzi i wyjaśnić, dlaczego i jak to działa;)
John WH Smith,
1
printf '%s\n' ①.php ②.php | sort | uniq -cdaje mi2 ①.php
Stéphane Chazelas
@ StéphaneChazelas Thats bo printf drukujephp\nphp
4
@Jidder, nie, to dlatego, że ①.phpsortuje się tak samo jak ②.phpw moim locale, ponieważ nie zdefiniowano kolejności sortowania dla tych i znaków w moim locale. Jeśli chcesz unikatowe wartości dla żadnej wartości bajtów (pamiętaj ścieżki plików niekoniecznie tekst), następnie trzeba naprawić locale C: | LC_ALL=C sort | LC_ALL=C uniq -c.
Stéphane Chazelas
2
Aby posortować wynikowy plik zliczania, należy rozważyć dodanie „sort -nr” jako odpowiedzi @ eduard-florinescu poniżej.
Lluís Suñol
104
[your command] | sort | uniq -c | sort -nr

Akceptowana odpowiedź jest prawie kompletna, możesz dodać sort -nrna końcu dodatkowy, aby posortować wyniki według linii, które występują najczęściej jako pierwsze

opcje uniq :

-c, --count
       prefix lines by the number of occurrences

opcje sortowania :

-n, --numeric-sort
       compare according to string numerical value
-r, --reverse
       reverse the result of comparisons

W konkretnym przypadku, gdy sortowane linie są liczbami, musisz użyć sort -grzamiast sort -nr, patrz komentarz

Eduard Florinescu
źródło
3
Dziękuję bardzo za poinformowanie mnie o -nopcji.
Sigur
2
Świetna odpowiedź, oto co mogę używać, aby uzyskać WordCount z pliku z wyroków: tr ' ' '\n' < $FILE | sort | uniq -c | sort -nr > wordcount.txt. Pierwsze polecenie zastępuje spacje nowymi wierszami, pozwalając na to, aby reszta polecenia działała zgodnie z oczekiwaniami.
Bar
2
Korzystając z powyższych opcji, otrzymuję „1” przed „23344”. Używanie sort -grzamiast tego rozwiązuje to. -g: porównaj według ogólnej wartości liczbowej (zamiast -n: porównaj według wartości liczbowej ciągu).
Peter Jaric
@PeterJaric Świetny haczyk i bardzo przydatne informacje, -grale myślę, że wynik uniq -cbędzie taki, że sort -nrbędzie działał zgodnie z przeznaczeniem
Eduard Florinescu
3
W rzeczywistości, gdy dane są liczbami, -grdziała lepiej. Wypróbuj te dwa przykłady, różniące się tylko flagami g i n: echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -nri echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -gr. Pierwszy sortuje niepoprawnie, ale nie drugi.
Peter Jaric
9

Możesz użyć tablicy asocjacyjnej na awk, a następnie - opcjonalnie - posortować :

cat access.log  | awk ' { tot[$0]++ } END { for (i in tot) print tot[i],i } ' | sort

wynik:

1 c.php
1 d.php
2 b.php
3 a.php
Laurence R. Ugalde
źródło
Jak policzyłbyś liczbę wystąpień, gdy potok wysyła dane?
user123456,