Zählen, wie oft jede IP-Adresse in der Protokolldatei angezeigt wird

9

Ich habe eine Datei im folgenden Format:

$ cat file.txt

27.33.65.2
27.33.65.2
58.161.137.7
121.50.198.5
184.173.187.1
184.173.187.1
184.173.187.1

Was ist der beste Weg, um die Datei file.txtin ein Format wie das folgende zu analysieren :

27.33.65.2: 2
58.161.137.7: 1
121.50.198.5: 1
184.173.187.1: 3

Mit anderen Worten, ich möchte die Datei durchlaufen und zählen, wie oft jede IP-Adresse angezeigt wird. Ich habe es bereits durchlaufen, sortdamit alle IP-Adressen in Ordnung und direkt nacheinander sind.

James Spittal
quelle
Ich persönlich würde diese Art von Datei in eine handliche Datenbank in der Nähe importieren (indem ich eine temporäre Tabelle in jeder Postgres-Instanz erstelle, die ich habe), gefolgt von einer schnellen SQL-Aktion und dem Export zurück in eine Textdatei.
Oakad

Antworten:

23

Du schaust nach uniq -c

Wenn die Ausgabe nicht Ihren Wünschen entspricht, kann sie problemlos analysiert und neu formatiert werden.

Zum Beispiel:

$ uniq -c logfile.txt | awk '{print $2": "$1}'
27.33.65.2: 2
58.161.137.7: 1
121.50.198.5: 1
184.173.187.1: 3
Glenn Jackman
quelle
Kombinieren uniqund awkscheint mir
kein guter
3
Weil uniqnur bei sortierten Eingaben funktioniert (es stimmt mit benachbarten übereinstimmenden Zeilen überein, nicht mit Zeilen aus der Datei).
Oakad
1
Sie müssen die Ergebnisse sortieren, bevor Sie sie an uniq weiterleiten. Wenn Sie das Original-Q lesen, gibt das OP an, dass er die Ergebnisse bereits mit sortiert hat sort!
slm
2
@HaukeLaging - Ich weiß zu schätzen, was Sie sagen, aber auf die gleiche Weise, wie sich die meisten Benutzer von Computern niemals über OSX und Windows hinaus wagen werden, werden sich die meisten Benutzer von Unix auch nicht über die Verwendung bestimmter Tools für bestimmte Aufgaben hinaus wagen. Die Verwendung von AWK ist nichts für schwache Nerven. Sehen Sie sich an, was Sie tun mussten, um diese grundlegende Aufgabe mit AWK auszuführen, und was Glenns Lösung erfordert. Ich denke, ich bin fair zu sagen, dass seine Lösung einfacher zu verstehen ist, obwohl Ihre wahrscheinlich effizienter ist. Übrigens habe ich beide UV gemacht, da beide korrekt sind!
slm
1
@HaukeLaging - Ja genau. Während Sie auf der Website herumhängen, ändern sich unsere Verantwortlichkeiten geringfügig, IMO. Wir sind dafür verantwortlich, umfassende A'er zu erstellen und die A'er zu betrachten, die wir dem OP und jedem zukünftigen Besucher, der darauf stößt, als Unterrichtsmomente anbieten, wieder IMO. Aber es ist eine persönliche Entscheidung. Wenn Sie nur ein paar Minuten Zeit haben, ist es immer willkommen, ein A in irgendeiner Form bereitzustellen.
slm
6

uniqscheint in der Tat die klügere Lösung zu sein. Der awk Weg:

awk '{ip_count[$0]++}; '\
'END {for (ip in ip_count) printf "%15s: %d\n",ip,ip_count[ip];}' file
Hauke ​​Laging
quelle
+1. Wenn die Reihenfolge der Ausgabe für das OP wichtig ist, gibt diese Antwort keine Garantie: Das Iterieren über die Schlüssel eines assoziativen Arrays hat keine inhärente Reihenfolge.
Glenn Jackman
@glennjackman Aber das Hinzufügen sortzu meiner Antwort ist immer noch schneller, da weniger Elemente sortiert werden müssen. ;-)
Hauke ​​Laging
Oh ja? OH JA?!? ;) die Eingabe ist bereits sortiert. Diese awk-Antwort mischt sie, also ist es noch mehr Arbeit. Nyah! ;)
Glenn Jackman
0

Die beste Sortierdatei wird dann von unic -c gezählt

sort filename | uniq -c

Aeyd Moeyd
quelle
1
Die Datei ist bereits sortiert (entsprechend dem Benutzer in der Frage) und uniq -cwürde funktionieren, aber die Ausgabe im falschen Format liefern. Aus diesem Grund wird in der akzeptierten Antwortsort die Ausgabe von nicht verwendet und stattdessen neu formatiert uniq -c.
Kusalananda
Danke @Aeyd. Ich habe nach diesem Befehl gesucht. Es hilft
user11392987
0

Ich würde Python verwenden. Auf jedem Linux-Stemem ist heutzutage Python2 installiert.

Fügen Sie jede IP-Adresse als Schlüssel = Wert-Paare in ein Diktat (assoziatives Array) ein, dh {"12.34.56.78": 1, "87.76.43.21": 3}.

Sie 'verifizieren' die IP-Adresse als Schlüssel und erhöhen den Wert um 1. Wenn Sie defaultdict ("ip") verwenden und der Schlüssel nicht vorhanden ist, wird er mit dem Standardwert 0 erstellt. Wenn der Schlüssel vorhanden ist Standarddict macht bereits nichts. Der Wert wird in der nächsten Zeile erhöht.

#!/usr/bin/python2

infile = open("file.txt","r")
iplist = {}  # create an empty dict

for line in infile:
    line = line.strip()   # remove newline.
    if line: # if not a blank line.
        iplist.setdefault(line, 0) # check for ip and add with default value of 0
        iplist[line] += 1 # increment

outfile = open("out.txt","w") #open output file

for key in iplist.keys():
    line = "%-15s = %s" % (key, iplist[key])
    print line   # print uf desired.
    outfile.write(line + "\n")

Outout-Datei:

cat out.txt                                                          
27.33.65.2      = 2
58.161.137.7    = 1
121.50.198.5    = 1
184.173.187.1   = 3

Ich weiß, dass Sie nach einer Befehlszeilenlösung gesucht haben, aber wie Sie sehen, handelt es sich um eine elegant formatierte Anzeige, die nur etwa ein Dutzend Zeilen benötigt. Python ist ein hervorragendes Tool für die Verwaltung.

Mike Childers
quelle