Sortieren und zählen Sie die Anzahl der Zeilen

145

Ich habe eine ApacheProtokolldatei, access.logwie wird die Anzahl der Zeilen in dieser Datei gezählt? das Ergebnis zum Beispiel cut -f 7 -d ' ' | cut -d '?' -f 1 | tr '[:upper:]' '[:lower:]'ist

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

Das gewünschte Ergebnis ist:

3 a.php
2 b.php
1 d.php # order doesn't matter
1 c.php 
Kokizzu
quelle
25
| sort | uniq -c
Costas
3
| LC_ALL=C sort | LC_ALL=C uniq -c
Stéphane Chazelas
ah, ich weiß nie, dass uniqdas tun könnte ..
Kokizzu
Haben Sie ein Beispiel für die Zeile im Protokoll, da ich denke, dass dies alles mit awk ohne alle Pipes gemacht werden könnte.
Es ist in Ordnung, 8,1 GB Protokolldatei in ca. 2 Minuten verarbeitet, und es ist fürs
Erste

Antworten:

196
| sort | uniq -c

Wie in den Kommentaren angegeben.

Durch Piping der Ausgabe in sortwird die Ausgabe in alphabetischer / numerischer Reihenfolge organisiert.

Dies ist eine Anforderung, da uniqnur Übereinstimmungen in wiederholten Zeilen, d. H

a
b
a

Wenn Sie uniqdiese Textdatei verwenden, wird Folgendes zurückgegeben:

a
b
a

Dies liegt daran, dass die beiden adurch das b- getrennt sind, es handelt sich nicht um aufeinanderfolgende Zeilen. Wenn Sie jedoch zuerst die Daten in alphabetischer Reihenfolge sortieren möchten

a
a
b

Dann uniqwerden die sich wiederholenden Linien entfernt. Die -cOption uniqzählt die Anzahl der Duplikate und liefert die Ausgabe in der Form:

2 a
1 b

Verweise:

visudo
quelle
1
Willkommen bei Unix & Linux :) Zögern Sie nicht, Ihrer Antwort weitere Details hinzuzufügen und zu erklären, warum und wie dies funktioniert;)
John WH Smith
1
printf '%s\n' ①.php ②.php | sort | uniq -cgibt mir2 ①.php
Stéphane Chazelas
@ StéphaneChazelas Das liegt daran, dass der printf drucktphp\nphp
4
@Jidder, nein, das liegt daran, dass die ①.phpSortierung mit der ②.phpin meinem Gebietsschema übereinstimmt, da für diese und die Zeichen in meinem Gebietsschema keine Sortierreihenfolge definiert ist . Wenn Sie eindeutige Werte für Byte-Werte wünschen (Dateipfade müssen nicht unbedingt Text sein), müssen Sie das Gebietsschema auf C: festlegen | LC_ALL=C sort | LC_ALL=C uniq -c.
Stéphane Chazelas
2
Um die resultierende Zähldatei sortieren zu lassen, sollten Sie erwägen, die "sort -nr" als @ eduard-florinescu Antworten unten hinzuzufügen.
Lluís Suñol
104
[your command] | sort | uniq -c | sort -nr

Die akzeptierte Antwort ist fast vollständig. Möglicherweise möchten Sie sort -nram Ende eine zusätzliche hinzufügen , um die Ergebnisse nach den Zeilen zu sortieren, die zuerst am häufigsten vorkommen

uniq optionen:

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

Sortiermöglichkeiten:

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

In dem speziellen Fall, in dem die Zeilen, die Sie sortieren, Zahlen sind, müssen Sie sort -grstattdessen verwenden sort -nr(siehe Kommentar)

Eduard Florinescu
quelle
3
Vielen Dank, dass Sie mich über die -nOption informiert haben .
Sigur
2
Große Antwort, hier ist, was ich mit Sätzen eine wordcount aus Datei erhalten verwenden tr ' ' '\n' < $FILE | sort | uniq -c | sort -nr > wordcount.txt. Der erste Befehl ersetzt Leerzeichen durch Zeilenumbrüche, sodass der Rest des Befehls wie erwartet ausgeführt werden kann.
Bar
2
Unter Verwendung der obigen Optionen erhalte ich "1" vor "23344". Verwenden Sie sort -grstattdessen, um dieses Problem zu lösen. -g: Vergleich nach allgemeinem Zahlenwert (statt -n: Vergleich nach Zahlenwert der Zeichenfolge).
Peter Jaric
@ PeterJaric Großartiger Fang und sehr nützlich zu wissen, -graber ich denke, die Ausgabe von uniq -cwird als solche sort -nrfunktionieren, wie beabsichtigt
Eduard Florinescu
3
Tatsächlich -grfunktioniert es besser , wenn die Daten Zahlen sind . Probieren Sie diese beiden Beispiele aus, die sich nur in den Flags g und n unterscheiden: echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -nrund echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -gr. Die erste Sortierung ist falsch, die zweite nicht.
Peter Jaric
9

Sie können ein assoziatives Array auf awk verwenden und dann -optional- sortieren :

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

Ausgabe:

1 c.php
1 d.php
2 b.php
3 a.php
Laurence R. Ugalde
quelle
Wie würden Sie die Anzahl der Vorkommen zählen, während die Pipe Daten sendet?
user123456