Correspondance négative à l'aide de grep (correspond à des lignes qui ne contiennent pas foo)

991

J'ai essayé de trouver la syntaxe de cette commande:

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

OU:

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

J'ai besoin de voir tous les fichiers qui ont été modifiés à l'exception de ceux nommés error_log.

J'ai lu à ce sujet ici , mais je n'ai trouvé qu'un notseul motif -regex.

jerrygarciuh
la source
13
[^ error_log] ne fonctionnerait jamais de toute façon, [] sont des classes de caractères, les expressions rationnelles en général ne sont pas bonnes pour les modèles négatifs (sauf si le moteur implémente des lookaheads négatifs).
Jaap

Réponses:

1758

grep -v est votre ami:

grep --help | grep invert  

-v, --invert-match sélectionner les lignes non correspondantes

Consultez également les connexes -L(le complément de -l).

-L, --files-without-match uniquement affiche les noms de FICHIER ne contenant aucune correspondance

Motti
la source
125
Il convient de mentionner que pour plusieurs matchs (négatifs), l' -eoption peut être utilisée:grep -v -e 'negphrase1' -e 'negphrase2'
Babken Vardanyan
31
Semblable au commentaire de @ Babken-Vardanyan Aussi - capable d'utiliser des tuyaux pour rejoindre plusieurs matchs, par exemplegrep -v 'negphrase1|negphrase2|negphrase3'
Nicholas Adams
13
Le dernier commentaire n'est PAS le même car il recherchera des choses qui ne correspondent pas aux deux plutôt qu'aux deux. c'est-à-dire s'il correspond à l'un mais pas à l'autre, il est toujours imprimé. Essayez-le dans les deux sens avec des cordes non similaires
Evan Langlois
7
@EvanLanglois - forçant grep à interpréter le motif comme une expression régulière étendue à l'aide d' -Eœuvres, c'estgrep -vE 'negphrase1|negphrase2|negphrase3'
Zlemini
1
@ OlleHärstedt, je pense que j'ai mal compris votre scénario dans mon commentaire précédent, ce qui suit peut être ce que vous recherchez grep "" /dev/null * | grep foo | grep -v bar | cut -d: -f1 | sort -u( pourquoi le premier grep?, Il y a toujours un moyen :))
Motti
139

Vous pouvez également utiliser awkà ces fins, car il vous permet d'effectuer des vérifications plus complexes d'une manière plus claire:

Lignes ne contenant pas foo:

awk '!/foo/'

Lignes ne contenant ni fooni bar:

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

Les lignes ne contenant ni fooni barqui contiennent soit foo2ou bar2:

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

Etc.

fedorqui 'SO arrête de nuire'
la source
2
C'est plutôt cool. Vous n'avez même pas besoin d'apprendre le langage awk complet pour regrouper l'expression rationnelle avec des opérateurs logiques. Merci pour cette réponse!
Peter T.
1
Exactement ce que je cherchais, merci beaucoup.
mmrs151
13

Dans votre cas, vous ne voulez probablement pas utiliser grep, mais ajoutez à la place une clause négative à la commande find, par exemple

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

Si vous souhaitez inclure des caractères génériques dans le nom, vous devrez les échapper, par exemple pour exclure les fichiers avec le suffixe .log:

find /home/baumerf/public_html/ -mmin -60 -not -name \*.log
grand Schtroumpf
la source