Contar el número de ocurrencias de un patrón en un archivo (incluso en la misma línea)


Cuando busco el número de ocurrencias de una cadena en un archivo, generalmente uso:

grep pattern file | wc -l

Sin embargo, esto solo encuentra una ocurrencia por línea, debido a la forma en que funciona grep. ¿Cómo puedo buscar el número de veces que aparece una cadena en un archivo, independientemente de si están en la misma línea o en líneas diferentes?

Además, ¿qué pasa si estoy buscando un patrón de expresiones regulares, no una simple cadena? ¿Cómo puedo contar esos, o, mejor aún, imprimir cada partido en una nueva línea?

Author: Amit G, 2010-05-26

5 answers

Para contar todas las ocurrencias, use -o. Prueba esto:

echo afoobarfoobar | grep -o foo | wc -l

Y man grep por supuesto (:

Actualización

Algunos sugieren usar solo grep -co foo en lugar de grep -o foo | wc -l.

No.{[16]]}

Este atajo no funcionará en todos los casos. La página de manual dice:

-c print a count of matching lines

La diferencia en estos enfoques se ilustra a continuación:

1.

$ echo afoobarfoobar | grep -oc foo
1

Tan pronto como se encuentre la coincidencia en la línea (a{foo}barfoobar) la búsqueda se detiene. Solo se comprobó una línea y coincidente, por lo que la salida es 1. En realidad -o se ignora aquí y podría usar grep -c en su lugar.

2.

$ echo afoobarfoobar | grep -o foo
foo
foo

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

Se encuentran dos coincidencias en la línea (a{foo}bar{foo}bar) porque pedimos explícitamente encontrar cada ocurrencia (-o). Cada ocurrencia se imprime en una línea separada, y wc -l solo cuenta el número de líneas en la salida.

 140
Author: hudolejev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-31 10:07:22

Prueba esto:

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

Muestra:

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
Author: IBrewThereforeIAm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-21 10:49:00

Un post tardío:
Utilice el patrón de expresiones regulares de búsqueda como Separador de registros (RS) en awk
Esto permite que su expresión regular abarque líneas delimitadas \n (si lo necesita).

printf 'X \n moo X\n XX\n' | 
   awk -vRS='X[^X]*X' 'END{print (NR<2?0:NR-1)}'
 1
Author: Peter.O,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-12 22:24:23

Ripgrep , que es una alternativa rápida a grep, acaba de introducir el indicador --count-matches que permite contar cada coincidencia en la versión 0.9 (estoy usando el ejemplo anterior para mantener la coherencia):

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

Como lo pidió OP, ripgrep también permite el patrón regex (--regexp <PATTERN>). También puede imprimir cada coincidencia (línea) en una línea separada:

> echo -e "line1foo\nline2afoobarfoobar" | rg foo
line1foo
line2afoobarfoobar
 0
Author: Sebastian Müller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-15 11:41:49

Hackea la función de color de grep y cuenta cuántas etiquetas de color imprime:

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
 -1
Author: Shizzmo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-25 22:05:21