Bash Script: policz unikalne linie w pliku


134

Sytuacja:

Mam duży plik (miliony wierszy) zawierający adresy IP i porty z kilku godzinnego przechwytywania sieci, po jednym IP / port na linię. Linie mają następujący format:

ip.ad.dre.ss[:port]

Pożądany rezultat:

Każdy pakiet, który otrzymałem podczas logowania, ma swój wpis, więc istnieje wiele zduplikowanych adresów. Chciałbym móc to uruchomić za pomocą jakiegoś skryptu powłoki, który będzie w stanie zredukować to do wierszy formatu

ip.ad.dre.ss[:port] count

gdzie countjest liczbą wystąpień tego konkretnego adresu (i portu). Nie trzeba wykonywać żadnych specjalnych czynności, traktuj różne porty jako różne adresy.

Do tej pory używam tego polecenia, aby zeskrobać wszystkie adresy IP z pliku dziennika:

grep -o -E [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(:[0-9]+)? ip_traffic-1.log > ips.txt

Z tego mogę użyć dość prostego wyrażenia regularnego, aby zeskrobać wszystkie adresy IP, które zostały wysłane z mojego adresu (co mnie nie obchodzi)

Następnie mogę użyć następujących elementów, aby wyodrębnić unikalne wpisy:

sort -u ips.txt > intermediate.txt

Nie wiem, jak mogę zagregować liczbę wierszy za pomocą sortowania.

Odpowiedzi:


309

Możesz użyć uniqpolecenia, aby uzyskać liczbę posortowanych powtórzonych wierszy:

sort ips.txt | uniq -c

Aby uzyskać najczęstsze wyniki na górze (dzięki Peter Jaric):

sort ips.txt | uniq -c | sort -bgr

11
Podoba mi się, jak -bgrprzypadkowo wygląda jak mnemonik dla bigger, którego chcemy na górze.
dwanderson

1
Jako mała dla funkcji .bashrclub .bash_aliasespliku: function countuniquelines () { sort "$1" | uniq -c | sort -bgr; }. Zadzwoń countuniquelines myfile.txt.
Johan

Nie wiem, dlaczego nie sort -nr.
Nakilon

6

Aby policzyć całkowitą liczbę unikalnych wierszy (tj. Nie biorąc pod uwagę zduplikowanych wierszy), możemy użyć uniqlub Awk z wc:

sort ips.txt | uniq | wc -l
awk '!seen[$0]++' ips.txt | wc -l

Tablice Awk są asocjacyjne, więc mogą działać trochę szybciej niż sortowanie.

Generowanie pliku tekstowego:

$  for i in {1..100000}; do echo $RANDOM; done > random.txt
$ time sort random.txt | uniq | wc -l
31175

real    0m1.193s
user    0m0.701s
sys     0m0.388s

$ time awk '!seen[$0]++' random.txt | wc -l
31175

real    0m0.675s
user    0m0.108s
sys     0m0.171s

Ciekawy. Może mieć
znaczącą

2

Jest to najszybszy sposób, aby uzyskać liczbę powtarzających się wierszy i ładnie je wydrukować w kolejności od najrzadziej do najczęstszych:

awk '{!seen[$0]++}END{for (i in seen) print seen[i], i}' ips.txt | sort -n

Jeśli nie zależy Ci na wydajności i chcesz czegoś łatwiejszego do zapamiętania, po prostu uruchom:

sort ips.txt | uniq -c | sort -n

PS:

sort -n analizuje pole jako liczbę, to prawda, ponieważ sortujemy przy użyciu liczników.


W tym !miejscu {!seen[$0]++}jest zbędne, ponieważ drukujemy tylko w pliku END.
Amir
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.