Zählen Sie alle Vorkommen einer Zeichenfolge in vielen Dateien mit grep

289

Ich habe ein paar Protokolldateien. Ich muss herausfinden, wie oft eine Zeichenfolge in allen Dateien vorkommt.

grep -c string *

kehrt zurück

...
file1:1
file2:0
file3:0
...

Mit einer Pipe konnte ich nur Dateien abrufen, die ein oder mehrere Vorkommen haben:

grep -c string * | grep -v :0

...
file4:5
file5:1
file6:2
...

Wie kann ich nur die kombinierte Anzahl erhalten? (Wenn es zurückkommt file4:5, file5:1, file6:2, möchte ich zurück 8.)

Željko Filipin
quelle
1
Kannst du mir sagen, was das grep -v: 0 macht? . Ich weiß, dass es für Dateien mit Vorkommen größer als 0 zählt. Was bedeutet die Option -v und: 0? Bitte lassen Sie es mich wissen.
Gautham Honnavara
@GauthamHonnavara grep: 0 sucht nach einer Zeile, die mit der Zeichenfolge übereinstimmt: 0. -v ist eine Option zum Umkehren dieser Suche. Verwenden Sie stattdessen grep -v: 0, um alle Zeilen zu finden, die nicht enthalten: 0, sodass eine Zeile mit file4: 5 und file27: 193 alle durchlaufen wird, da sie nicht enthalten: 0
Pinguin359
Sie können mehrere Dateien mit Leerzeichen auswählen. grep file1 file2 --options
Dnyaneshwar Harer

Antworten:

288
cat * | grep -c string
Bombe
quelle
9
Dies hat die gleiche Einschränkung, dass mehrere Vorkommen in einer Zeile nur einmal gezählt werden. Ich vermute jedoch, dass dieses Verhalten in diesem Fall in Ordnung ist.
Michael Haren
@ Michael Haren Ja, es kann nur ein Zeichenfolgenvorgang in einer Zeile geben.
Željko Filipin
2
Ich würde es lieber tun, grep -c string<*also nur den Platz durch einen weniger als ersetzen.
JamesM-SiteGen
48
Behandelt nicht mehrere Vorkommen auf einer Linie
Bluesman
2
Dies funktioniert nicht, wenn Sie auch in Unterverzeichnissen suchen möchten, wohingegen grep -ound wc -l. Katze ist in Fällen wie der ursprünglichen Frage jedoch schneller.
Leagsaidh Gordon
296

Dies funktioniert für mehrere Vorkommen pro Zeile:

grep -o string * | wc -l
Jeremy Lavine
quelle
2
Dies funktioniert auch : grep -o string * --exclude-dir=some/dir/one/ --exclude-dir=some/dir/two | wc -l.
Ein Codierer
2
grep -ioR string * | wc -list das, was ich benutze, um eine Suche ohne
Berücksichtigung der
2
Dieser zeigt die relevanten Dateien und dann die Gesamtzahl der Übereinstimmungen:grep -rc test . | awk -F: '$NF > 0 {x+=$NF; $NF=""; print} END{print "Total:",x}'
Yaron
28
grep -oh string * | wc -w

zählt mehrere Vorkommen in einer Zeile

Kaofu
quelle
24
grep -oh "... my that curry was strong" * >> wc:)
icc97
23

Anstatt -c zu verwenden, leiten Sie es einfach an wc -l weiter.

grep string * | wc -l

Dadurch wird jedes Vorkommen in einer einzelnen Zeile aufgelistet und anschließend die Anzahl der Zeilen gezählt.

Dadurch werden jedoch Fälle übersehen, in denen die Zeichenfolge in einer Zeile mehr als 2 Mal vorkommt.

Michael Haren
quelle
2
Das Piping zu "wc -l" funktioniert auch gut zusammen mit "grep -r 'test'." Dadurch werden alle Dateien in allen Verzeichnissen unterhalb des aktuellen rekursiv nach dem String 'test' durchsucht.
Stevek
16
cat * | grep -c string

Eine der seltenen nützlichen Anwendungen von cat.

Joachim Sauer
quelle
9

Etwas anderes als alle vorherigen Antworten:

perl -lne '$count++ for m/<pattern>/g;END{print $count}' *
Vijay
quelle
Es ist schön zu sehen, dass ein Ansatz kein grep verwendet, zumal mein grep (unter Windows) die Option -o nicht unterstützt.
David Roussel
9

Sie können hinzufügen -R, um rekursiv zu suchen (und die Verwendung von cat zu vermeiden) und -IBinärdateien zu ignorieren.

grep -RIc string .
Azmeuk
quelle
7

Obligatorische AWK-Lösung:

grep -c string * | awk 'BEGIN{FS=":"}{x+=$2}END{print x}'

Seien Sie vorsichtig, wenn Ihre Dateinamen ":" enthalten.

mumrah
quelle
5

Die AWK-Lösung, die auch Dateinamen einschließlich Doppelpunkte verarbeitet:

grep -c string * | sed -r 's/^.*://' | awk 'BEGIN{}{x+=$1}END{print x}'

Beachten Sie, dass diese Methode immer noch nicht mehrere Vorkommen stringin derselben Zeile findet.

Kreuvf
quelle
4

Wenn Sie die Anzahl der Vorkommen pro Datei möchten (Beispiel für die Zeichenfolge "tcp"):

grep -RIci "tcp" . | awk -v FS=":" -v OFS="\t" '$2>0 { print $2, $1 }' | sort -hr

Beispielausgabe:

53  ./HTTPClient/src/HTTPClient.cpp
21  ./WiFi/src/WiFiSTA.cpp
19  ./WiFi/src/ETH.cpp
13  ./WiFi/src/WiFiAP.cpp
4   ./WiFi/src/WiFiClient.cpp
4   ./HTTPClient/src/HTTPClient.h
3   ./WiFi/src/WiFiGeneric.cpp
2   ./WiFi/examples/WiFiClientBasic/WiFiClientBasic.ino
2   ./WiFiClientSecure/src/ssl_client.cpp
1   ./WiFi/src/WiFiServer.cpp

Erläuterung:

  • grep -RIci NEEDLE . - sucht rekursiv nach der Zeichenfolge NEEDLE aus dem aktuellen Verzeichnis (nach Symlinks), ignoriert Binärdateien, zählt die Anzahl der Vorkommen und ignoriert Groß- und Kleinschreibung
  • awk ... - Dieser Befehl ignoriert Dateien mit null Vorkommen und formatiert Zeilen
  • sort -hr - Sortiert die Zeilen in umgekehrter Reihenfolge nach Zahlen in der ersten Spalte

Natürlich funktioniert es auch mit anderen grep-Befehlen mit Option -c(Anzahl). Zum Beispiel:

grep -c "tcp" *.txt | awk -v FS=":" -v OFS="\t" '$2>0 { print $2, $1 }' | sort -hr
Andriy Makukha
quelle
3

Sie können eine einfache grepMethode verwenden , um die Anzahl der Vorkommen effektiv zu erfassen. Ich werde die -iOption verwenden, um sicherzustellen, STRING/StrING/stringdass sie richtig erfasst wird.

Befehlszeile, die den Namen der Dateien angibt:

grep -oci string * | grep -v :0

Befehlszeile, die die Dateinamen entfernt und 0 druckt, wenn eine Datei ohne Vorkommen vorhanden ist:

grep -ochi string *
Mitul Patel
quelle
Könnten Sie bitte Ihre Antwort näher erläutern und etwas mehr Beschreibung der von Ihnen angebotenen Lösung hinzufügen?
Abarisone
3

kurze rekursive Variante:

find . -type f -exec cat {} + | grep -c 'string'
Dmitry Tarashkevich
quelle
1
Danke dir! Nur Ihre Lösung hat bei mir funktioniert (summiert die Übereinstimmungen aller Dateien).
Nestor
1

Nur Grep-Lösung, die ich mit grep für Windows getestet habe:

grep -ro "pattern to find in files" "Directory to recursively search" | grep -c "pattern to find in files"

Diese Lösung zählt alle Vorkommen, auch wenn mehrere in einer Zeile vorhanden sind. -rDurchsucht rekursiv das Verzeichnis und -ozeigt "nur den Teil einer Zeile an, der mit MUSTER übereinstimmt" - dies teilt mehrere Vorkommen in einer einzelnen Zeile auf und lässt grep jede Übereinstimmung in einer neuen Zeile drucken. Leiten Sie dann diese durch Zeilenumbrüche getrennten Ergebnisse zurück in grep mit, -cum die Anzahl der Vorkommen nach demselben Muster zu zählen.

Quantic
quelle
1

Hier ist eine alternative AWK-Alternative, die mehrere Übereinstimmungen <url>pro Zeile in einer Sammlung von XML-Dateien in einem Verzeichnis verarbeitet:

awk '/<url>/{m=gsub("<url>","");total+=m}END{print total}' some_directory/*.xml

Dies funktioniert gut in Fällen, in denen einige XML-Dateien keine Zeilenumbrüche aufweisen.

Excalibur
quelle
0

Ein weiterer Oneliner, der grundlegende Befehlszeilenfunktionen verwendet, behandelt mehrere Vorkommen pro Zeile.

 cat * |sed s/string/\\\nstring\ /g |grep string |wc -l
NTwoO
quelle