Conta grep in tutte le occorrenze di una stringa in molti file


289

Ho un sacco di file di registro. Devo scoprire quante volte si verifica una stringa in tutti i file.

grep -c string *

ritorna

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

Utilizzando una pipe sono stato in grado di ottenere solo file con una o più occorrenze:

grep -c string * | grep -v :0

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

Come posso ottenere solo il conteggio combinato? (Se ritorna file4:5, file5:1, file6:2, voglio tornare indietro 8.)


1
Puoi dirmi cosa fa grep -v: 0? . So che conta per i file con occorrenze maggiori di 0. Cosa significano l'opzione -v e: 0? Gentilmente fammi sapere.
Gautham Honnavara,

@GauthamHonnavara grep: 0 cerca la linea che corrisponde alla stringa: 0. -v è un'opzione per invertire quella ricerca, quindi invece usando grep -v: 0 significa trovare tutte le righe che non contengono: 0, quindi una riga con file4: 5 e file27: 193 passerebbe attraverso poiché non contengono: 0
penguin359,

Puoi selezionare più file usando lo spazio. grep file1 file2 --options
Dnyaneshwar Harer,

Risposte:


288
cat * | grep -c string

9
Ciò ha la stessa limitazione che conta più ricorrenze su una riga una sola volta. Immagino che questo comportamento sia OK in questo caso, però.
Michael Haren,

@Michael Haren Sì, potrebbe esserci solo un'occorrenza di stringa in una riga.
Željko Filipin,

2
Preferirei fare grep -c string<*così Sostituendo semplicemente lo spazio con un meno di.
JamesM-SiteGen

48
Non risolve più occorrenze su una riga
bluesman

2
Questo non funziona se si desidera effettuare la ricerca nelle sottodirectory troppo, mentre grep -oe wc -llo fa. cat è più veloce in casi come la domanda originale però.
Leagsaidh Gordon,

296

Questo funziona per più occorrenze per riga:

grep -o string * | wc -l

2
Questo funziona anche: grep -o string * --exclude-dir=some/dir/one/ --exclude-dir=some/dir/two | wc -l.
un programmatore il

2
grep -ioR string * | wc -lè quello che uso per fare una ricerca senza distinzione tra maiuscole e minuscole, ricorsiva, solo di corrispondenza
LeonardChallis,

2
Questo mostra i file pertinenti e quindi il conteggio totale delle partite:grep -rc test . | awk -F: '$NF > 0 {x+=$NF; $NF=""; print} END{print "Total:",x}'
Yaron,

28
grep -oh string * | wc -w

conterà più occorrenze in una riga


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

23

Invece di usare -c, esegui semplicemente il pipe su wc -l.

grep string * | wc -l

Questo elencherà ogni occorrenza su una singola riga e quindi conteggerà il numero di righe.

Tuttavia, ciò mancherà i casi in cui la stringa si verifica più di 2 volte su una riga.


2
Il piping su "wc -l" funziona bene anche con "grep -r 'test'". che esegue la scansione ricorsiva di tutti i file per la stringa "test" in tutte le directory al di sotto di quella corrente.
Stevek,


9

Qualcosa di diverso rispetto a tutte le risposte precedenti:

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

è bello vedere un approccio che non usa grep, specialmente perché il mio grep (su windows) non supporta l'opzione -o.
David Roussel,

9

Puoi aggiungere la -Rricerca ricorsivamente (ed evitare di usare cat) e -Iignorare i file binari.

grep -RIc string .

7

Soluzione AWK obbligatoria:

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

Fai attenzione se i nomi dei tuoi file includono ":" però.


5

La soluzione AWK che gestisce anche i nomi dei file tra cui due punti:

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

Tieni presente che questo metodo non trova ancora più occorrenze stringsulla stessa riga.


4

Se si desidera il numero di occorrenze per file (esempio per la stringa "tcp"):

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

Esempio di output:

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

Spiegazione:

  • grep -RIci NEEDLE . - cerca la stringa NEEDLE ricorsivamente dalla directory corrente (seguendo i collegamenti simbolici), ignorando i binari, contando il numero di occorrenze, ignorando il caso
  • awk ... - questo comando ignora i file con zero occorrenze e righe di formati
  • sort -hr - ordina le righe in ordine inverso in base ai numeri nella prima colonna

Ovviamente, funziona anche con altri comandi grep con l'opzione -c(count). Per esempio:

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

3

È possibile utilizzare un semplice grepper catturare il numero di occorrenze in modo efficace. Userò l' -iopzione per assicurarmi di STRING/StrING/stringessere catturato correttamente.

Riga di comando che dà il nome del file:

grep -oci string * | grep -v :0

Riga di comando che rimuove i nomi dei file e stampa 0 se esiste un file senza occorrenze:

grep -ochi string *

Potresti per favore elaborare di più la tua risposta aggiungendo un po 'più di descrizione della soluzione che offri?
abarisone,

3

breve variante ricorsiva :

find . -type f -exec cat {} + | grep -c 'string'

1
Grazie! Solo la tua soluzione ha funzionato per me (ha riassunto le corrispondenze di tutti i file).
Nestor,

1

L'unica soluzione Grep che ho testato con grep per Windows:

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

Questa soluzione conterà tutte le occorrenze anche se ce ne sono più su una riga. -rcerca ricorsivamente nella directory, -o"mostrerà solo la parte di una riga corrispondente a PATTERN" - questo è ciò che divide più occorrenze su una sola riga e fa in modo che grep stampi ogni corrispondenza su una nuova riga; quindi reindirizzare i risultati separati da nuova riga in grep con -cper contare il numero di occorrenze utilizzando lo stesso modello.


1

Ecco un modo alternativo AWK più veloce di grep per farlo, che gestisce più corrispondenze di <url>per riga, all'interno di una raccolta di file XML in una directory:

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

Funziona bene nei casi in cui alcuni file XML non presentano interruzioni di riga.


0

Un altro oneliner che utilizza le funzioni di base della riga di comando gestisce più ricorrenze per riga.

 cat * |sed s/string/\\\nstring\ /g |grep string |wc -l
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.