Cuente todas las apariciones de una cadena en muchos archivos con grep

289

Tengo un montón de archivos de registro. Necesito averiguar cuántas veces ocurre una cadena en todos los archivos.

grep -c string *

devoluciones

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

Usando una tubería pude obtener solo archivos que tienen una o más ocurrencias:

grep -c string * | grep -v :0

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

¿Cómo puedo obtener solo el recuento combinado? (Si vuelve file4:5, file5:1, file6:2, quiero volver a 8.)

Željko Filipin
fuente
1
¿Me puede decir qué hace el grep -v: 0? . Sé que cuenta para archivos que tienen ocurrencias mayores que 0. ¿Qué significa la opción -v y: 0? Amablemente hágamelo saber.
Gautham Honnavara
@GauthamHonnavara grep: 0 busca una línea que coincida con la cadena: 0. -v es una opción para invertir esa búsqueda, por lo que en su lugar usar grep -v: 0 significa buscar todas las líneas que no contienen: 0 para que una línea con file4: 5 y file27: 193 todas pasen, ya que no contienen: 0
penguin359
Puede seleccionar múltiples archivos usando el espacio. grep file1 file2 --options
Dnyaneshwar Harer

Respuestas:

288
cat * | grep -c string
Bombe
fuente
99
Esto tiene la misma limitación que cuenta las ocurrencias múltiples en una línea solo una vez. Sin embargo, supongo que este comportamiento está bien en este caso.
Michael Haren
@ Michael Haren Sí, solo puede haber una aparición de cadena en una línea.
Željko Filipin
2
Prefiero hacerlo, grep -c string<*solo reemplazando el espacio con un menor que.
JamesM-SiteGen
48
No aborda múltiples ocurrencias en una línea
bluesman
2
Esto no funciona si desea buscar en los subdirectorios también, mientras que grep -oy wc -llo hace. Sin embargo, cat es más rápido en casos como la pregunta original.
Leagsaidh Gordon
296

Esto funciona para múltiples ocurrencias por línea:

grep -o string * | wc -l
Jeremy Lavine
fuente
2
Esto también funciona: grep -o string * --exclude-dir=some/dir/one/ --exclude-dir=some/dir/two | wc -l.
un codificador
2
grep -ioR string * | wc -les lo que uso para hacer una búsqueda que no distingue entre mayúsculas y minúsculas, recursiva, solo coincidente
LeonardChallis
2
Este muestra los archivos relevantes y luego el conteo total de partidos:grep -rc test . | awk -F: '$NF > 0 {x+=$NF; $NF=""; print} END{print "Total:",x}'
Yaron
28
grep -oh string * | wc -w

contará múltiples ocurrencias en una línea

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

En lugar de usar -c, solo conéctelo a wc -l.

grep string * | wc -l

Esto enumerará cada aparición en una sola línea y luego contará el número de líneas.

Sin embargo, esto perderá instancias en las que la cadena ocurra más de 2 veces en una línea.

Michael Haren
fuente
2
La conexión a "wc -l" también funciona muy bien junto con "grep -r 'test'". que escanea recursivamente todos los archivos para la cadena 'prueba' en todos los directorios debajo del actual.
stevek
16
cat * | grep -c string

Una de las raras aplicaciones útiles de cat.

Joachim Sauer
fuente
9

Algo diferente a todas las respuestas anteriores:

perl -lne '$count++ for m/<pattern>/g;END{print $count}' *
Vijay
fuente
Es bueno ver un enfoque que no utiliza grep, especialmente porque mi grep (en Windows) no admite la opción -o.
David Roussel
9

Puede agregar -Rpara buscar de forma recursiva (y evitar usar cat) e -Iignorar los archivos binarios.

grep -RIc string .
azmeuk
fuente
7

Solución obligatoria de AWK:

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

Sin embargo, tenga cuidado si sus nombres de archivo incluyen ":".

mumrah
fuente
5

La solución AWK que también maneja nombres de archivos incluyendo dos puntos:

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

Tenga en cuenta que este método todavía no encuentra múltiples ocurrencias stringen la misma línea.

Kreuvf
fuente
4

Si desea un número de ocurrencias por archivo (ejemplo para la cadena "tcp"):

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

Salida de ejemplo:

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

Explicación:

  • grep -RIci NEEDLE . - busca la AGUJA de cadena recursivamente del directorio actual (siguiendo los enlaces simbólicos), ignorando los binarios, contando el número de ocurrencias, ignorando las mayúsculas y minúsculas
  • awk ... - este comando ignora los archivos con cero apariciones y formatea líneas
  • sort -hr - ordena las líneas en orden inverso por números en la primera columna

Por supuesto, también funciona con otros comandos grep con la opción -c(cuenta). Por ejemplo:

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

Puede utilizar un simple greppara capturar la cantidad de ocurrencias de manera efectiva. Usaré la -iopción para asegurarme de que STRING/StrING/stringme capturen correctamente.

Línea de comando que da el nombre de los archivos:

grep -oci string * | grep -v :0

Línea de comando que elimina los nombres de archivo e imprime 0 si hay un archivo sin ocurrencias:

grep -ochi string *
Mitul Patel
fuente
¿Podría por favor elaborar más su respuesta agregando un poco más de descripción sobre la solución que proporciona?
abarisone
3

variante recursiva corta :

find . -type f -exec cat {} + | grep -c 'string'
Dmitry Tarashkevich
fuente
1
¡Gracias! Solo su solución funcionó para mí (resumió las coincidencias de todos los archivos).
Néstor el
1

Solución única de Grep que probé con grep para Windows:

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

Esta solución contará todas las ocurrencias, incluso si hay múltiples en una línea. -rbusca recursivamente en el directorio, -o"mostrará solo la parte de una línea que coincide con PATTERN": esto es lo que divide múltiples ocurrencias en una sola línea y hace que grep imprima cada coincidencia en una nueva línea; luego canalice esos resultados separados por una nueva línea nuevamente en grep -cpara contar el número de ocurrencias utilizando el mismo patrón.

Quantic
fuente
1

Aquí hay una forma alternativa de AWK más rápida que grep de hacer esto, que maneja múltiples coincidencias de <url>por línea, dentro de una colección de archivos XML en un directorio:

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

Esto funciona bien en casos donde algunos archivos XML no tienen saltos de línea.

Excalibur
fuente
0

Otro oneliner que utiliza funciones básicas de línea de comandos que manejan múltiples ocurrencias por línea.

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