web-dev-qa-db-fra.com

Comment grep, en excluant certains motifs?

Je voudrais trouver des lignes dans les fichiers avec une occurrence d'un motif et une absence d'un autre motif. Par exemple, j'ai besoin de trouver tous les fichiers/lignes, y compris loom à l'exception des fichiers avec gloom. Donc, je peux trouver loom avec la commande:

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

Maintenant, je veux rechercher loom excluant 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 et gloom sont les séquences de caractères (pas nécessairement les mots). Donc, j'ai besoin, par exemple, de bloomberg dans la sortie de la commande et je n'ai pas besoin de ungloomy.

EDIT 2: Voici un exemple de mes attentes . Les deux lignes suivantes sont dans la sortie de la commande:

J'ai fait face aux icônes qui apparaissaient à travers le voile de l'encens. 

Arty, c'est {fainéant) dans un sombre jour.

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

C’est gloomyin ’ ower terrible - de superbes portiers muckle o’ les assauts.

Dans le sud-ouest de la hauteur de la salle pyntit

62
Loom

Pourquoi ne pas enchaîner les greps?

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

Une autre solution sans chaîner grep:

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

Entre parenthèses, vous excluez le caractère g avant toute occurrence de loom, sauf si loom est le premier caractère de la ligne.

15
Bentoy13

Un peu vieux, mais bon ...

La solution la plus votée de @houbysoft ne fonctionnera pas, car elle exclura toute ligne contenant "de la morosité", même si elle a "loom". Selon les attentes de OP, nous devons inclure des lignes avec "loom", même si elles sont également "sombres". Cette ligne doit figurer dans la sortie "Arty est en pagaille dans un jour maussade.", Mais cela sera exclu par un grep chaîné comme 

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)

comme il inclura toute ligne avec "métier à tisser" dans celui-ci, qu'il soit ou non "sombre". D'un autre côté, s'il ne fait que sombre, il ne l'inclura pas, ce qui est précisément le comportement souhaité par OP.

8
Sam

Il suffit d'utiliser awk, il est beaucoup plus simple que grep de vous permettre d'exprimer clairement les conditions composées.

Si vous souhaitez ignorer les lignes contenant à la fois loom et 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 par lui-même:

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

/ * Vous cherchez peut-être quelque chose comme ça?

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

Les BACKQUOTES sont utilisés comme des crochets pour les commandes, donc dans ce cas avec -l activé, Le code dans les BACKQUOTES vous renverra les noms de fichier, puis avec -vn pour faire ce que vous voulez: lignes réelles. 

UPDATEOu avec xargs

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

J'espère que cela pourra aider.*/

S'il vous plaît, ignorez ce que j'ai écrit ci-dessus, c'est de la foutaise. 

grep -n "loom" `grep -l "loom" tt4.txt` | grep -v "gloom"

               #this part gets the filenames with "loom"
#this part gets the lines with "loom"
                                          #this part gets the linenumber,
                                          #filename and actual line
5
Juto

Vous pouvez utiliser grep -P (Perl regex) supporté negative lookbehind:

grep -P '(?<!g)loom\b' ~/projects/**/trunk/src/**/*.@(h|cpp)

J'ai ajouté \b pour les limites de Word.

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

Utilisez simplement! grep -v plusieurs fois.

Contenu du fichier

[root@server]# cat file
1
2
3
4
5

Exclure la ligne ou le match

[root@server]# cat file |grep -v 3
1
2
4
5

Exclure la ligne ou faire correspondre plusieurs

[root@server]# cat file |grep -v 3 |grep -v 5
1
2
4
1
Tiborcz Kiss

Question: rechercher 'métier à tisser' à l'exclusion de 'morosité'. 
Réponse:

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