it-swarm.com.de

Anzahl der Vorkommen eines Musters in einer Datei zählen (auch in derselben Zeile)

Bei der Suche nach Anzahl der Vorkommen einer Zeichenfolge in einer Datei verwende ich im Allgemeinen Folgendes:

grep pattern file | wc -l

Dies findet jedoch aufgrund der Funktionsweise von grep nur ein Vorkommen pro Zeile. Wie kann ich nach der Häufigkeit suchen, in der eine Zeichenfolge in einer Datei angezeigt wird, unabhängig davon, ob sie in derselben oder in unterschiedlichen Zeilen stehen?

Was passiert, wenn ich nach einem Regex-Muster suche, nicht nach einer einfachen Zeichenfolge? Wie kann ich diese zählen oder noch besser jede Übereinstimmung in einer neuen Zeile ausdrucken?

83
jrdioko

Um alle Vorkommen zu zählen, verwenden Sie -o. Versuche dies:

echo afoobarfoobar | grep -o foo | wc -l

Und man grep natürlich (:

Aktualisieren

Einige schlagen vor, nur grep -co foo anstelle von grep -o foo | wc -l zu verwenden.

Nicht.

Diese Verknüpfung funktioniert nicht in allen Fällen. Manpage sagt:

-c print a count of matching lines

Der Unterschied in diesen Ansätzen ist unten dargestellt:

1.

$ echo afoobarfoobar | grep -oc foo
1

Sobald die Übereinstimmung gefunden wird, wird die Suche gestoppt. In der Zeile (a{foo}barfoobar). Es wurde nur eine Zeile geprüft und es wurde eine Übereinstimmung gefunden, daher lautet die Ausgabe 1. Eigentlich wird -o hier ignoriert und Sie können stattdessen einfach grep -c verwenden.

2.

$ echo afoobarfoobar | grep -o foo
foo
foo

$ echo afoobarfoobar | grep -o foo | wc -l
2

In der Zeile (a{foo}bar{foo}bar) werden zwei Übereinstimmungen gefunden, da wir ausdrücklich nach jedem Vorkommen (-o) gesucht haben. Jedes Vorkommen wird in einer separaten Zeile gedruckt, und wc -l zählt nur die Anzahl der Zeilen in der Ausgabe.

143
hudolejev

Versuche dies:

grep "string to search for" FileNameToSearch | cut -d ":" -f 4 | sort -n | uniq -c

Probe:

grep "SMTP connect from unknown" maillog | cut -d ":" -f 4 | sort -n | uniq -c
  6  SMTP connect from unknown [188.190.118.90]
 54  SMTP connect from unknown [62.193.131.114]
  3  SMTP connect from unknown [91.222.51.253]
2

Ein verspäteter Beitrag:
Verwenden Sie das Suchregex-Muster als Datensatztrennzeichen (RS) in awk.
Damit kann Ihr Regex \n- getrennte Zeilen umfassen (wenn Sie es brauchen). 

printf 'X \n moo X\n XX\n' | 
   awk -vRS='X[^X]*X' 'END{print (NR<2?0:NR-1)}'
1
Peter.O

Ripgrep , eine schnelle Alternative zu grep, hat gerade das --count-matches-Flag eingeführt, das das Zählen von each in Version 0.9 ermöglicht (Ich verwende das obige Beispiel, um konsistent zu bleiben):

> echo afoobarfoobar | rg --count foo
1
> echo afoobarfoobar | rg --count-matches foo
2

Wie von OP verlangt, erlaubt ripgrep auch ein reguläres Ausdrückmuster (--regexp <PATTERN>) . Außerdem kann jeder (Zeilen-) Treffer in einer separaten Zeile gedruckt werden:

> echo -e "line1foo\nline2afoobarfoobar" | rg foo
line1foo
line2afoobarfoobar
0