108 votes

Comment grep, en excluant certains motifs ?

J'aimerais trouver les lignes dans les fichiers avec une occurrence d'un certain modèle et une absence d'un autre modèle. Par exemple, j'ai besoin de trouver tous les fichiers/lignes comprenant loom sauf ceux qui ont gloom . Donc, je peux trouver loom avec commandement :

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

Maintenant, je veux chercher loom à l'exclusion de gloom . Cependant, les deux commandes suivantes ont échoué :

grep -v 'gloom' -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
grep -n 'loom' -v 'gloom' ~/projects/**/trunk/src/**/*.@(h|cpp)

Que dois-je faire pour atteindre mon objectif ?

EDIT 1 : Je veux dire que loom y gloom sont les séquences de caractères (pas nécessairement les mots). J'ai donc besoin, par exemple, de bloomberg dans la sortie de la commande et n'ont pas besoin de ungloomy .

EDIT 2 : Il y a un échantillon de mes attentes. Les deux lignes suivantes sont dans la sortie de commande :

J'ai fait face aux icônes que tissé à travers le voile de l'encens.

Arty est (en anglais) dans un sombre jour.

Les deux lignes suivantes ne sont pas dans la sortie de commande :

C'est lugubre C'est terrible - de grands faiseurs de cloches.

Dans le rond sud-ouest de la salle du Heigh Pyntit.

132voto

houbysoft Points 9773

Pourquoi ne pas simplement enchaîner les greps ?

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

27voto

Bentoy13 Points 1868

Une autre solution sans chaînage grep :

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

Entre parenthèses, vous excluez le caractère g avant tout événement de loom à moins que loom est le premier caractère de la ligne.

12voto

Sam Points 169

Un peu vieux, mais bon...

La solution la plus votée de @houbysoft ne fonctionnera pas car elle exclura toute ligne contenant "gloom", même si elle contient "loom". Selon les attentes du PO, nous devons inclure les lignes contenant "loom", même si elles contiennent également "gloom". Cette ligne doit être incluse dans la sortie "Arty is slooming in a gloomy day.", mais elle sera exclue par un grep chaîné tel que

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

Au lieu de cela, le egrep regex exemple de Bentoy13 fonctionne mieux

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

car elle inclura toute ligne contenant "loom", qu'elle contienne ou non "gloom". En revanche, si elle ne contient que "gloom", elle ne l'inclura pas, ce qui est précisément le comportement souhaité par le PO.

9voto

Ed Morton Points 25374

Utilisez simplement awk, il est beaucoup plus simple que grep pour vous permettre d'exprimer clairement des conditions composées.

Si vous voulez sauter les lignes qui contiennent à la fois loom y gloom :

awk '/loom/ && !/gloom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

ou si vous voulez les imprimer :

awk '/(^|[^g])loom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

et si la réalité est que vous voulez juste des lignes où loom apparaît comme un mot à part entière :

awk '/\<loom\>/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

7voto

Oleg Kokorin Points 396

-v est le drapeau "correspondance inversée", donc le piping est un très bon moyen :

grep "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)| grep -v "gloom"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X