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 count
jest 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.
-bgr
przypadkowo wygląda jak mnemonik dlabigger
, którego chcemy na górze..bashrc
lub.bash_aliases
pliku:function countuniquelines () { sort "$1" | uniq -c | sort -bgr; }
. Zadzwońcountuniquelines myfile.txt
.sort -nr
.Aby policzyć całkowitą liczbę unikalnych wierszy (tj. Nie biorąc pod uwagę zduplikowanych wierszy), możemy użyć
uniq
lub Awk zwc
: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
źródło
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:
PS:
sort -n analizuje pole jako liczbę, to prawda, ponieważ sortujemy przy użyciu liczników.
źródło
!
miejscu{!seen[$0]++}
jest zbędne, ponieważ drukujemy tylko w plikuEND
.