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


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

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

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


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.


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


9

Algo diferente a todas las respuestas anteriores:

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

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 .

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 ":".


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.


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

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 *

¿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'

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.


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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.