Abbinamento negativo usando grep (abbina le linee che non contengono pippo)


991

Ho cercato di elaborare la sintassi per questo comando:

grep ! error_log | find /home/foo/public_html/ -mmin -60

O:

grep '[^error_log]' | find /home/baumerf/public_html/ -mmin -60

Ho bisogno di vedere tutti i file che sono stati modificati tranne quelli denominati error_log.

Ne ho letto qui , ma ho trovato solo uno notschema -regex.


13
[^ error_log] non funzionerebbe mai, in ogni caso, [] sono classi di caratteri, in generale i regexp non sono adatti a schemi negativi (a meno che il motore non implementi visi negativi).
Jaap

Risposte:


1758

grep -v È tuo amico:

grep --help | grep invert  

-v, --invert-match seleziona linee non corrispondenti

Dai un'occhiata anche al relativo -L(il complemento di -l).

-L, --files-senza-match stampa solo i nomi FILE che non contengono corrispondenze


125
Vale la pena ricordare che per più partite (negative) è -epossibile utilizzare l'opzione:grep -v -e 'negphrase1' -e 'negphrase2'
Babken Vardanyan,

31
Simile al commento di @ Babken-Vardanyan Anche - in grado di utilizzare le pipe per unire più partite, ad esempiogrep -v 'negphrase1|negphrase2|negphrase3'
Nicholas Adams,

13
L'ultimo commento NON è lo stesso in quanto cercherà elementi che non corrispondono a entrambi anziché a nessuno dei due. cioè se corrisponde a uno ma non all'altro è ancora stampato. Provalo in entrambi i modi con stringhe non simili
Evan Langlois il

7
@EvanLanglois - forzare grep a interpretare il modello come un'espressione regolare estesa usando le -Eopere, ovvero grep -vE 'negphrase1|negphrase2|negphrase3'
Zlemini

1
@ OlleHärstedt, penso di aver frainteso il tuo scenario nel mio commento precedente, il seguente potrebbe essere quello che stai cercando grep "" /dev/null * | grep foo | grep -v bar | cut -d: -f1 | sort -u( perché il primo grep ? , c'è sempre un modo :))
Motti

139

È inoltre possibile utilizzare awkper questi scopi, poiché consente di eseguire controlli più complessi in modo più chiaro:

Linee non contenenti foo:

awk '!/foo/'

Linee che non contengono né foobar:

awk '!/foo/ && !/bar/'

Linee contenenti né foobarche contengono uno foo2o bar2:

awk '!/foo/ && !/bar/ && (/foo2/ || /bar2/)'

E così via.


2
In realtà è abbastanza bello. Non è nemmeno necessario imparare la lingua awk completa per raggruppare regexp con operatori logici. Grazie per questa risposta!
Peter T.

1
Esattamente quello che stavo cercando, grazie mille.
mmrs151

13

Nel tuo caso, presumibilmente non vuoi usare grep, ma aggiungi invece una clausola negativa al comando find, ad es

find /home/baumerf/public_html/ -mmin -60 -not -name error_log

Se vuoi includere i caratteri jolly nel nome, dovrai evitarli, ad esempio per escludere i file con il suffisso .log:

find /home/baumerf/public_html/ -mmin -60 -not -name \*.log
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.