Bash-Skript: Zählen Sie eindeutige Zeilen in der Datei

129

Lage:

Ich habe eine große Datei (Millionen von Zeilen) mit IP-Adressen und Ports aus einer mehrstündigen Netzwerkerfassung, eine IP / Port pro Zeile. Zeilen haben dieses Format:

ip.ad.dre.ss[:port]

Erwünschtes Ergebnis:

Für jedes Paket, das ich während der Protokollierung erhalten habe, gibt es einen Eintrag, daher gibt es viele doppelte Adressen. Ich möchte dies durch ein Shell-Skript ausführen können, das es auf Zeilen des Formats reduzieren kann

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

Wo countist die Anzahl der Vorkommen dieser bestimmten Adresse (und Port). Es müssen keine besonderen Arbeiten durchgeführt werden. Behandeln Sie verschiedene Ports als unterschiedliche Adressen.

Bisher verwende ich diesen Befehl, um alle IP-Adressen aus der Protokolldatei zu entfernen:

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

Daraus kann ich einen ziemlich einfachen regulären Ausdruck verwenden, um alle IP-Adressen herauszukratzen, die von meiner Adresse gesendet wurden (was mir egal ist).

Ich kann dann Folgendes verwenden, um die eindeutigen Einträge zu extrahieren:

sort -u ips.txt > intermediate.txt

Ich weiß nicht, wie ich die Zeilenanzahl irgendwie mit sortieren aggregieren kann.

Wug
quelle

Antworten:

303

Mit dem uniqBefehl können Sie die Anzahl der sortierten wiederholten Zeilen abrufen:

sort ips.txt | uniq -c

Um die häufigsten Ergebnisse oben zu erzielen (danke an Peter Jaric):

sort ips.txt | uniq -c | sort -bgr
Michael Hoffman
quelle
10
Mir gefällt, wie -bgrzufällig eine Mnemonik aussieht bigger, was wir oben wollen.
Dwanderson
1
Als kleine Funktion für Ihre .bashrcoder .bash_aliasesDatei : function countuniquelines () { sort "$1" | uniq -c | sort -bgr; }. Rufen Sie an countuniquelines myfile.txt.
Johan
Ich weiß nicht warum nicht sort -nr.
Nakilon
5

Um zählt die Gesamtzahl der einzelnen Linien (dh ohne Berücksichtigung von doppelten Zeilen) können wir verwenden uniqoder Awk mit wc:

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

Awks Arrays sind assoziativ, sodass sie möglicherweise etwas schneller als das Sortieren ausgeführt werden.

Textdatei generieren:

$  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
qwr
quelle
Interessant.
Könnte
1

Dies ist der schnellste Weg, um die Anzahl der wiederholten Zeilen zu ermitteln und sie schön drucken zu lassen, sortiert nach den am wenigsten häufigen bis den häufigsten:

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

Wenn Sie sich nicht für die Leistung interessieren und etwas möchten, an das Sie sich leichter erinnern können, führen Sie einfach Folgendes aus:

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

PS:

sort -n parse das Feld als Zahl, das ist richtig, da wir nach den Zählwerten sortieren.

Luca Mastrostefano
quelle
Das !In {!seen[$0]++}ist hier überflüssig, da wir nur das Drucken am END.
Amir