95 votes

Compter le nombre d'occurrences d'un motif dans un fichier (même sur une même ligne)

Lorsque je recherche le nombre d'occurrences d'une chaîne dans un fichier, j'utilise généralement :

grep pattern file | wc -l

Toutefois, cela ne permet de trouver qu'une seule occurrence par ligne, en raison de la façon dont grep fonctionne. Comment puis-je rechercher le nombre d'occurrences d'une chaîne dans un fichier, qu'elles se trouvent sur la même ligne ou sur des lignes différentes ?

De même, que se passe-t-il si je recherche un motif regex et non une simple chaîne de caractères ? Comment puis-je les compter, ou, encore mieux, imprimer chaque correspondance sur une nouvelle ligne ?

160voto

hudolejev Points 2053

Pour compter toutes les occurrences, utilisez -o . Essayez ceci :

echo afoobarfoobar | grep -o foo | wc -l

Y man grep bien sûr ( :

Mise à jour

Certains suggèrent d'utiliser uniquement grep -co foo au lieu de grep -o foo | wc -l .

Ne le faites pas.

Ce raccourci ne fonctionnera pas dans tous les cas. La page de manuel dit :

-c print a count of matching lines

La différence entre ces approches est illustrée ci-dessous :

1.

$ echo afoobarfoobar | grep -oc foo
1

Dès que la correspondance est trouvée dans la ligne ( a{foo}barfoobar ) la recherche s'arrête. Une seule ligne a été vérifiée et elle correspond, donc la sortie est la suivante 1 . En fait, -o est ignorée ici et vous pourriez simplement utiliser grep -c à la place.

2.

$ echo afoobarfoobar | grep -o foo
foo
foo

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

Deux correspondances sont trouvées dans la ligne ( a{foo}bar{foo}bar ) parce que nous avons explicitement demandé de trouver chaque occurrence ( -o ). Chaque occurrence est imprimée sur une ligne distincte, et wc -l compte simplement le nombre de lignes dans la sortie.

1 votes

Wow... c'est vraiment aussi simple que ça ?

1 votes

Grep -oc ne fonctionne pas dans ce cas. Essayez echo afoobarfoobar | grep -oc foo

0 votes

N'y a-t-il pas moyen de faire cela pour plusieurs fichiers ? Disons que je veux voir le nombre d'occurrences par fichier sur un ensemble de fichiers. Je peux le faire par ligne avec grep -c *, mais pas par instance.

2voto

user3846048 Points 21

Essayez ça :

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

Échantillon :

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]

1voto

Peter.O Points 1911

Un post tardif :
Utilisez le modèle de recherche regex comme séparateur d'enregistrement (RS) dans le fichier awk
Cela permet à votre regex de couvrir \n -lignes délimitées (si vous en avez besoin).

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

0voto

Sebastian Müller Points 215

Ripgrep qui est une alternative rapide à grep, vient d'introduire la fonction --count-matches drapeau permettant le comptage chaque dans la version 0.9 (j'utilise l'exemple ci-dessus pour rester cohérent) :

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

Comme demandé par l'OP, ripgrep permet aussi les motifs regex ( --regexp <PATTERN> ). Il peut également imprimer chaque correspondance (ligne) sur une ligne séparée :

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

-1voto

Shizzmo Points 4695

Piratez la fonction de couleur de grep, et comptez le nombre d'étiquettes de couleur qu'elle affiche :

echo -e "a\nb  b b\nc\ndef\nb e brb\nr" \
| GREP_COLOR="033" grep --color=always  b \
| perl -e 'undef $/; $_=<>; s/\n//g; s/\x1b\x5b\x30\x33\x33/\n/g; print $_' \
| wc -l

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X