Wie grep, ohne einige Muster?


84

Ich möchte Zeilen in Dateien finden, in denen ein Muster vorkommt und ein anderes Muster fehlt. Zum Beispiel muss ich alle Dateien / Zeilen finden, loomaußer denen mit gloom. Also kann ich loommit Befehl finden:

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

Jetzt möchte ich loomausschließen suchen gloom. Beide der folgenden Befehle sind jedoch fehlgeschlagen:

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

Was soll ich tun, um mein Ziel zu erreichen?

EDIT 1: Ich meine dasloomundgloomsind die Zeichenfolgen (nicht unbedingt die Wörter). So brauche ich zum Beispielbloombergin der Befehlsausgabe und brauche nichtungloomy.

EDIT 2: Es gibt eine Stichprobe meiner Erwartungen. Beide der folgenden Zeilen befinden sich in der Befehlsausgabe:

Ich konfrontiert die Symbole , die ragte durch den Schleier von Weihrauch.

Arty dämmert an einem düsteren Tag.

Die beiden folgenden Zeilen sind nicht in der Befehlsausgabe enthalten:

Es ist düster, schrecklich - große Mistkerle von Cloods.

In der südwestlichen Runde der Heigh Pyntit Hall


Suchen Sie nach Dateien, die Ihren Kriterien entsprechen, oder nach Zeilen, die Ihren Kriterien entsprechen?
Juto

Ich suche nach Dateien mit Zeilen, die meinen Kriterien entsprechen. Und ich möchte die Liste aller Sätze Dateiname + Nummer der übereinstimmenden Zeile + übereinstimmende Zeile selbst sehen.
Webstuhl

Wenn die Zeile there is a loom in the gloomwäre - möchten Sie, dass diese Zeile gedruckt wird? Ich versuche nur zu verstehen, ob Sie nur nach Linien suchen, bei denen der Webstuhl nicht als Teil der Dunkelheit auftritt, oder ob Sie Linien, die die Dunkelheit enthalten, wirklich ausschließen möchten, selbst wenn der Webstuhl an einer anderen Stelle in der Linie eigenständig erscheint. Das Posten von Beispieleingaben und erwarteten Ausgaben würde helfen.
Ed Morton

Ihre Frage ist also wirklich How do I find lines containing the string "loom" where "loom" is not preceded by the letter "g"? Wenn Sie einige Beispieleingaben und die gewünschte Ausgabe gepostet hätten, hätte dies sehr geholfen. Die Antwort auf diese Frage finden Sie in den Antworten unten.
Ed Morton

1
@ EdMorton - Ja, du hast recht - ich brauche alle Zeilen, wo loomohne Vorzeichen vorkommt g. (Es tut mir leid. Ich habe gestern angefangen zu kommentieren, bin aber nie fertig geworden. Aus Versehen wurde dieser Kommentar gesendet.)
Loom

Antworten:


102

Wie wäre es einfach die Greps zu verketten?

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

13
Gerade rechtzeitig. Funktioniert perfekt. -v ist die Option zum Ausschließen. Danke
Ravi Krishna P

2
Aus der Frage: Also brauche ich zum Beispiel bloombergin der Befehlsausgabe und brauche nicht ungloomy. Wenn eine einzelne Zeile "... und Bloomberg ist düster in Bezug auf die Aussichten ..." enthält, würden Sie diese Zeile entfernen, aber sie ist erwünscht (denn wenn sie enthält bloomberg).
Jonathan Leffler

23

Eine andere Lösung ohne Verkettung grep:

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

In Klammern schließen Sie das Zeichen gvor jedem Auftreten von aus loom, es loomsei denn, es handelt sich um die ersten Zeichen der Zeile.


9

Ein bisschen alt, aber na ja ...

Die am besten gewählte Lösung von @houbysoft funktioniert nicht, da dadurch keine Zeile mit "Finsternis" ausgeschlossen wird, selbst wenn sie "Webstuhl" enthält. Gemäß den Erwartungen von OP müssen wir Linien mit "Webstuhl" einfügen, auch wenn sie auch "Trübsinn" enthalten. Diese Zeile muss in der Ausgabe "Arty dämmert an einem düsteren Tag" stehen, dies wird jedoch durch ein verkettetes Grep wie ausgeschlossen

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

Stattdessen funktioniert das egrep-Regex- Beispiel von Bentoy13 besser

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

da es jede Zeile mit "Webstuhl" enthält, unabhängig davon, ob es "Finsternis" hat oder nicht. Auf der anderen Seite wird es, wenn es nur düster ist, es nicht einschließen, was genau das Verhalten ist, das OP will.


8

Verwenden Sie einfach awk, es ist viel einfacher als grep, wenn Sie zusammengesetzte Bedingungen klar ausdrücken können.

Wenn Sie möchten , Zeilen überspringen, enthält beide loomund gloom:

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

oder wenn Sie sie drucken möchten:

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

und wenn die Realität ist, wollen Sie nur Zeilen, in denen loomein Wort für sich erscheint:

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

3
Überlegen Sie , wie Sie einen Befehl grep schreiben würde Linien zu erhalten , die enthalten abcund defund ghiin beliebiger Reihenfolge. Vergleichen Sie das jetzt mit awk '/abc/ && /def/ && /ghi/'. Denken Sie nun darüber nach, wie das grep-Äquivalent von awk '/loom/ && !/gloom/'in den Antworten auf dieser Seite geschrieben wird.
Ed Morton

Ich bin mit awk nicht sehr vertraut, anscheinend gibt es Bücher über diesen Befehl für sich. Im Moment geht es mir gut mit grep, vielleicht werde ich eines Tages dasselbe sagen, was du getan hast. :)
Juto

2
awk ist DAS Standard-UNX-Tool (dh für ALLE UNIX-Installationen verfügbar) zur Verarbeitung von Textdateien. Dafür wurde es erfunden und es ist sehr gut darin. Wenn Sie unter UNIX arbeiten und Textdateien analysieren, lernen Sie awk aus dem Buch Effective Awk Programming, Third Edition von Arnold Robins. Es gibt einen kleinen Paradigmenwechsel, der im Zusammenhang mit der awks- condition { action }Syntax überwunden werden muss, aber dann ist es ein Kinderspiel für alle, die C- oder andere Algol- basierte Spracherfahrungen haben.
Ed Morton

Bonus: Ausgabe wie grep -Hn --color:awk '/loom/ && !/gloom/ { gsub(/loom/, color("1;31") "&" color(0)); print color(35) FILENAME color(36) ":" color(32) FNR color(36) ":" color(0) $0; }; function color(c) { return "\033[" c "m"; }'
Gewirr

6

-v ist das Flag "Inverted Match", daher ist Piping ein sehr guter Weg:

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


5

/ * Du siehst vielleicht so aus?

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

Die BACKQUOTES werden wie Klammern für Befehle verwendet. In diesem Fall -lgibt der Code in den BACKQUOTES bei Aktivierung die Dateinamen zurück und dann mit -vn, um das zu tun, was Sie wollten: Dateinamen, Leinenzahlen und auch die tatsächlichen Zeilen.

UPDATE Oder mit xargs

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

Hoffentlich hilft das.*/

Bitte ignorieren Sie, was ich oben geschrieben habe, es ist Müll.

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

4

Sie können grep -P(Perl Regex) unterstützt verwenden negative lookbehind:

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

Ich habe \bfür Wortgrenzen hinzugefügt .


2
Sie brauchen kein Aussehen, \([^g]\|^\)funktioniert. Und dies schließt Zeilen mit loomund nicht aus gloom.
Kevin

@ Kevin: OP will aber Linien mit Webstuhl finden not gloom.
Anubhava

Genau. Wenn eine Linie beides hat, will er es nicht, aber das passt trotzdem dazu.
Kevin

@ Kevin: Dies entspricht NICHT der Dunkelheit, sondern dem Webstuhl (wie OP es wünscht).
Anubhava

Aus der Frage: Also brauche ich zum Beispiel bloombergin der Befehlsausgabe und brauche nicht ungloomy. Somit sind die Wortgrenzen kontraproduktiv.
Jonathan Leffler

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

Aus der Frage: Also brauche ich zum Beispiel bloombergin der Befehlsausgabe und brauche nicht ungloomy. Wenn eine einzelne Zeile "... und Bloomberg ist düster in Bezug auf die Aussichten ..." enthält, würden Sie diese Zeile entfernen, aber sie ist erwünscht (denn wenn sie enthält bloomberg).
Jonathan Leffler

@ JonathanLeffler "Ich muss alle Dateien / Zeilen einschließlich Webstuhl finden, außer denen mit Trübsinn."
Jiminion

3

Einfach benutzen! grep -vmehrmals.

Inhalt der Datei

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

Schließen Sie die Linie oder Übereinstimmung aus

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

Schließen Sie die Linie aus oder stimmen Sie mit mehreren überein

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

0

Frage: Suche nach 'Webstuhl' ohne 'Finsternis'.
Antworten:

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

1
Aus der Frage: Also brauche ich zum Beispiel bloombergin der Befehlsausgabe und brauche nicht ungloomy. Ich denke nicht, dass dies -wdie Lösung für dieses Rätsel ist.
Jonathan Leffler
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.