Compter toutes les occurrences d'une chaîne dans de nombreux fichiers avec grep

289

J'ai un tas de fichiers journaux. J'ai besoin de savoir combien de fois une chaîne se produit dans tous les fichiers.

grep -c string *

Retour

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

En utilisant un canal, j'ai pu obtenir uniquement des fichiers qui ont une ou plusieurs occurrences:

grep -c string * | grep -v :0

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

Comment puis-je obtenir uniquement le nombre combiné? (S'il revient file4:5, file5:1, file6:2, je veux en revenir 8.)

Željko Filipin
la source
1
Pouvez-vous me dire ce que fait le grep -v: 0? . Je sais que cela compte pour les fichiers ayant des occurrences supérieures à 0. Que signifie l'option -v et: 0 signifie?. Veuillez me le faire savoir.
Gautham Honnavara
@GauthamHonnavara grep: 0 recherche la ligne qui correspond à la chaîne: 0. -v est une option pour inverser cette recherche afin d'utiliser à la place grep -v: 0 signifie trouver toutes les lignes qui ne contiennent pas: 0 donc une ligne avec file4: 5 et file27: 193 passerait toutes car elles ne contiennent pas: 0
penguin359
Vous pouvez sélectionner plusieurs fichiers en utilisant l'espace. grep file1 file2 --options
Dnyaneshwar Harer

Réponses:

288
cat * | grep -c string
Bombe
la source
9
Cela a la même limitation qu'il compte plusieurs occurrences sur une seule ligne une seule fois. Je suppose que ce comportement est correct dans ce cas, cependant.
Michael Haren
@Michael Haren Oui, il ne peut y avoir qu'une seule occurrence de chaîne dans une ligne.
Željko Filipin
2
Je préfère le faire en grep -c string<*remplaçant simplement l'espace par un moins de.
JamesM-SiteGen
48
Ne traite pas de plusieurs occurrences sur une ligne
bluesman
2
Cela ne fonctionne pas si vous souhaitez également rechercher dans les sous-répertoires, contrairement à grep -oet wc -l. le chat est plus rapide dans des cas comme la question d'origine.
Leagsaidh Gordon
296

Cela fonctionne pour plusieurs occurrences par ligne:

grep -o string * | wc -l
Jeremy Lavine
la source
2
Cela fonctionne aussi: grep -o string * --exclude-dir=some/dir/one/ --exclude-dir=some/dir/two | wc -l.
un codeur
2
grep -ioR string * | wc -lest ce que j'utilise pour faire une recherche insensible à la casse, récursive et par correspondance uniquement
LeonardChallis
2
Celui-ci montre les fichiers pertinents puis le nombre total de matchs:grep -rc test . | awk -F: '$NF > 0 {x+=$NF; $NF=""; print} END{print "Total:",x}'
Yaron
28
grep -oh string * | wc -w

comptera plusieurs occurrences dans une ligne

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

Au lieu d'utiliser -c, dirigez-le simplement vers wc -l.

grep string * | wc -l

Cela répertoriera chaque occurrence sur une seule ligne, puis comptera le nombre de lignes.

Cependant, cela manquera les cas où la chaîne se produit 2 fois ou plus sur une même ligne.

Michael Haren
la source
2
Le piping vers "wc -l" fonctionne aussi très bien avec "grep -r 'test'". " qui analyse récursivement tous les fichiers pour la chaîne «test» dans tous les répertoires en dessous du répertoire actuel.
stevek
16
cat * | grep -c string

L'une des rares applications utiles de cat.

Joachim Sauer
la source
9

Quelque chose de différent de toutes les réponses précédentes:

perl -lne '$count++ for m/<pattern>/g;END{print $count}' *
Vijay
la source
agréable de voir une approche n'utilisant pas grep, surtout que mon grep (sous Windows) ne prend pas en charge l'option -o.
David Roussel
9

Vous pouvez ajouter -Rà la recherche récursivement (et éviter d'utiliser cat) et -Iignorer les fichiers binaires.

grep -RIc string .
azmeuk
la source
7

Solution AWK obligatoire:

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

Attention cependant si les noms de vos fichiers contiennent ":".

mumrah
la source
5

La solution AWK qui gère également les noms de fichiers, y compris les deux-points:

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

Gardez à l'esprit que cette méthode ne trouve toujours pas plusieurs occurrences de stringsur la même ligne.

Kreuvf
la source
4

Si vous souhaitez un nombre d'occurrences par fichier (exemple pour la chaîne "tcp"):

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

Exemple de sortie:

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

Explication:

  • grep -RIci NEEDLE . - recherche la chaîne NEEDLE de manière récursive à partir du répertoire courant (suivant les liens symboliques), en ignorant les binaires, en comptant le nombre d'occurrences, en ignorant la casse
  • awk ... - cette commande ignore les fichiers avec zéro occurrence et formate les lignes
  • sort -hr - trie les lignes dans l'ordre inverse par des nombres dans la première colonne

Bien sûr, cela fonctionne également avec d'autres commandes grep avec l'option -c(count). Par exemple:

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

Vous pouvez utiliser un simple greppour capturer efficacement le nombre d'occurrences. J'utiliserai l' -ioption pour m'assurer d' STRING/StrING/stringêtre correctement capturé.

Ligne de commande qui donne le nom des fichiers:

grep -oci string * | grep -v :0

Ligne de commande qui supprime les noms de fichiers et affiche 0 s'il y a un fichier sans occurrence:

grep -ochi string *
Mitul Patel
la source
Pourriez-vous élaborer davantage votre réponse en ajoutant un peu plus de description sur la solution que vous proposez?
abarisone
3

variante récursive courte :

find . -type f -exec cat {} + | grep -c 'string'
Dmitry Tarashkevich
la source
1
Je vous remercie! Seule votre solution a fonctionné pour moi (résumé des correspondances de tous les fichiers).
Nestor
1

Grep seule solution que j'ai testée avec grep pour windows:

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

Cette solution comptera toutes les occurrences même s'il y en a plusieurs sur une même ligne. -rrecherche récursivement dans le répertoire, -o"n'affichera que la partie d'une ligne correspondant au MOTIF" - c'est ce qui divise plusieurs occurrences sur une seule ligne et fait grep imprimer chaque correspondance sur une nouvelle ligne; redirigez ensuite ces résultats séparés par des sauts de ligne dans grep avec -cpour compter le nombre d'occurrences en utilisant le même modèle.

Quantic
la source
1

Voici une autre façon de procéder AWK plus rapide que grep, qui gère plusieurs correspondances <url>par ligne, dans une collection de fichiers XML dans un répertoire:

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

Cela fonctionne bien dans les cas où certains fichiers XML n'ont pas de sauts de ligne.

Excalibur
la source
0

Un autre oneliner utilisant des fonctions de ligne de commande de base gérant plusieurs occurrences par ligne.

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