grep per "termine" ed escludere "un altro termine"


28

Sto cercando di costruire una ricerca grep che cerca un termine ma esclude le righe che hanno un secondo termine. Volevo usare più -e "pattern"opzioni ma non ha funzionato.

Ecco un esempio di un comando che ho provato e del messaggio di errore che ha generato.

grep -i -E "search term" -ev "exclude term"
grep: exclude term: No such file or directory

Mi sembra che ciò si -vapplichi a tutti i termini / modelli di ricerca. Poiché viene eseguito ma non include search termnei risultati.

grep -i -E "search term" -ve "exclude term"

C'è qualche altra opzione per escludere, come a volte dobbiamo grep linee attorno a una parola e se escludiamo nella prossima operazione usando '|' , rimuove solo quella parola ma non rimuove il blocco per quella parola
Learner

Risposte:


40

Per ed espressioni con grep sono necessarie due invocazioni:

grep -Ei "search term" | grep -Eiv "exclude term"

Se i termini che stai cercando non sono espressioni regolari, utilizza una corrispondenza di stringa fissa ( -F) che è più veloce:

grep -F "search term" | grep -Fv "exclude term"

18

A meno di invocare grep due volte, c'è solo un modo a cui riesco a pensare di farlo. Comprende le espressioni regolari compatibili (PCRE) di Perl e alcune asserzioni piuttosto confuse .

Per cercare foo escludendo le partite che contengono barra , puoi usare:

grep -P '(?=^((?!bar).)*$)foo'

Ecco come funziona:

  • (?!bar)corrisponde a tutto ciò che non è barra senza consumare caratteri dalla stringa. Quindi .consuma un singolo personaggio.

  • ^((?!bar).)*ripete quanto sopra dall'inizio della stringa ( ^) alla fine di essa ( $). Fallirà se barsi incontra in un dato punto, poiché (?!bar)non corrisponderà.

  • (?=^((?!bar).)*$) si assicura che la stringa corrisponda al modello precedente, senza consumare caratteri dalla stringa.

  • foocerca foo come al solito.

Ho trovato questo hack nell'espressione regolare per abbinare la stringa che non contiene una parola? . Nella risposta di Bart Kiers , puoi trovare una spiegazione molto più dettagliata di come opera la prospettiva negativa.


Bel trucco. Questo trucco funziona anche in Java, tra l'altro.
Raman,

12

Se vuoi farlo in un solo passaggio, puoi usare awk invece di grep.

Formato:

echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'

Esempi:

  • echo "hello there" | awk '/hello/ && !/there/'

Non restituisce nulla.

  • echo "hello thre" | awk '/hello/ && !/there/'

Ritorni: ciao tre

  • echo "hllo there" | awk '/hello/ && !/there/'

Non restituisce nulla.

Per più motivi, è possibile utilizzare la parentesi per raggrupparli.

Esempi:

  • echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'

Ritorni: ciao tre

  • echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'

Ritorni: ciao tre

  • echo "hello there" | awk '(/hello/ || /hi/) && !/there/'

Non restituisce nulla.

  • echo "hi there" | awk '(/hello/ || /hi/) && !/there/'

Non restituisce nulla.


1
Ha funzionato per me, ma ho perso i colori = P
Leopoldo Sanczyk il

1
Colori da quale uscita? Se stai cercando di conservare i colori con ls, usa l'argomento "--color = always" ogni volta che analizzi l'output (o normalmente perderai sempre i colori quando analizzi il testo). Esempio: ls --color=always | awk '/hello/ && !/goodbye/'
Philip Reese,

Grazie per la risposta @Philip! L'ho provato prima, ma senza successo. Immagino che dato che il modello ha il testo colorato, non corrisponderà più tardi e dovrei includere un tipo di codice colore nel modello. Ad ogni modo, il tuo è il modo più veloce che ho scoperto di fare grep -Rin diversi file di codice usando la riga di comando di Ubuntu.
Leopoldo Sanczyk,

1

Dai miei esperimenti non sembra fare molta differenza se installi i tuoi termini di esclusione attraverso grepo sed. Sed ha alcune altre utili funzioni di sostituzione del testo che uso spesso per filtrare meglio l'output dei file di registro. Quindi userò sed perché combinerò un bel numero di filtri su sed.

wc /var/log/tomcat/tomcat.2013-01-14.log.1 
  1851725

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK / d" -e "/ Login scaduto / d" | bagno
24.05user 0.15system 0: 25.27 CPU 95% scaduta (0avgtext + 0avgdata 3504maxresident) k
0inputs + 0outputs (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK / d" -e "/ Login scaduto / d" | bagno
23.50utente 0.16sistema 0: 24.48 CPU 96% scaduta (0avgtext + 0avgdata 3504maxresident) k
0inputs + 0outputs (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "login OK" -e "Login scaduto" | bagno
23.08utente 0.14sistema 0: 23.55 CPU 98% scaduta (0avgtext + 0avgdata 3504maxresident) k
0inputs + 0outputs (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "login OK" -e "Login scaduto" | bagno
23.50utente 0.15sistema 0: 25.27 CPU 93% scaduta (0avgtext + 0avgdata 3488maxresident) k
0inputs + 0outputs (0major + 245minor) pagefaults 0swaps
   5614 91168 1186298


3
Prova a confrontare il runtime di grep -Finvece di grep -Ee non utilizzarlo -ise non ti serve.
Thor,

1
Ma poi non fornisci esempi usando sed;)
Benjamin R
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.