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.)


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

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

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


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.


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


9

Etwas anderes als alle vorherigen Antworten:

perl -lne '$count++ for m/<pattern>/g;END{print $count}' *

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 .

7

Obligatorische AWK-Lösung:

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

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


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.


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

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 *

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'

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.


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.


0

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

 cat * |sed s/string/\\\nstring\ /g |grep string |wc -l
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.