So suchen Sie mit grep nach dem Vorkommen eines Wortes und dem Fehlen eines anderen

So suchen Sie mit grep nach dem Vorkommen eines Wortes und dem Fehlen eines anderen

Ich habe eine Datei mit ähnlichem Inhalt wie:

google.com,9,AB+CD,nonAB+nonCD
youtube.com,9,AB+CD,AB+CD
facebook.com,20,AB+CD,nonCD

Die Anzahl der Spalten ist nicht festgelegt. Die erste Spalte enthält eine URL, die zweite eine Zahl und ab der dritten Spalte durch Kommas getrennte Schlüsselwörter, die jedoch von Site zu Site unterschiedlich sind.

Ich möchte die Anzahl der URLs (Zeilen) zählen, bei denen ich kontrollieren kann, welche Schlüsselwörter in der Zeile stehen. Zum Beispiel
1) AB+CDohne nonABund nonCD. Hinweis: Das Wort AB+CD kann mehrfach vorkommen. 2) AB+CD ohne Vorkommen von nonCD(aber es ist ok, wenn etwas anderes vorkommt)

Wie suche ich nach einer Zeichenfolge in einer Zeile UND stelle sicher, dass keine andere Zeichenfolge vorhanden ist. Ich verwende:

grep 'AB+CD' test.txt > result.txt

Es druckt jede Zeile, in der „AB+CD“ gefunden wird.

Was passiert, wenn ich die Zeile ausdrucken möchte, in der nur „AB+CD“ steht, um Folgendes zu erhalten:

youtube.com,9,AB+CD,AB+CD

Oder es gibt „AB+CD“ mit allem anderen außer „nonAB“, um Folgendes zu erhalten:

youtube.com,9,AB+CD,AB+CD
facebook.com,20,AB+CD,nonCD

Antwort1

Wenn Sie nur eine reine Textsuche durchführen möchten und nicht auf die Spalten achten möchten, können Sie die invertierte Übereinstimmung grep -vfolgendermaßen verketten:

cat input.txt | grep 'IncludedText' | grep -v 'ExcludedText'

Wenn Sie richtig nach Spalte filtern möchten, sollten Sie etwas wie verwenden awk.

Antwort2

Allgemeine Tricks:

  1. Zeilen mit fooPluszeichen, Zeilen mit bar( foo OR bar):

    grep -e foo -e bar
    
  2. Zeilen, die foound barin der gleichen Zeile enthalten ( foo AND bar):

    grep foo | grep bar
    
  3. Zeilen, die keine baz( NOT baz) enthalten:

    grep -v baz
    

Mit diesen Bausteinen können Sie Ihre Logik aufbauen. Das Problem ist, -vdass es nicht auf ein einzelnes Muster beschränkt ist, sondern global für alles grep(zumindest in meinem Debian). Dies ermöglicht NOT (foo OR bar):

grep -v -e foo -e bar

was gleichbedeutend ist mit (NOT foo) AND (NOT bar):

grep -v foo | grep -v bar

Allerdings ist NOT (foo AND bar)(logisch äquivalent zu (NOT foo) OR (NOT bar)) nicht so einfach. Wir können versuchen, foo AND barmit einemeinzel(erweitert) grep:

  1. Wiederum Zeilen, die foound barin der gleichen Zeile enthalten ( foo AND bar):

    grep -E 'foo.*bar|bar.*foo'
    

Jetzt erhalten Sie NOT (foo AND bar):

grep -v -E 'foo.*bar|bar.*foo'

Ich bin mir nicht sicher, ob das obige System vollständig ist, wenn man mit mehr als zwei Mustern arbeitet. Dennoch sind einige Ihrer Probleme damit lösbar. Beispiel:

AB+CDohne nonABundnonCD

Wenn ich Sie richtig verstehe, dann ist esAB+CD AND NOT (nonAB OR nonCD)

grep AB+CD | grep -v -e nonAB -e nonCD

Beachten Sie, dass diese Anfrage die Dinge komplizierter macht:

Ich möchte die Zeile drucken, in der nur „AB+CD“ steht

Man könnte sagen, grep ,AB+CD,AB+CDdas reicht, aber da „die Anzahl der Spalten nicht festgelegt ist“, würden Sie vermutlich diese beiden Zeilen unterscheiden wollen:

youtube.com,9,AB+CD,AB+CD,AB+CD
youtube.com,9,AB+CD,AB+CD,banana

In solchen Fällen benötigen Sie kompliziertere reguläre Ausdrücke oder andere Tools (wie awk).

Antwort3

Während Sie hier eine Antwort erhalten, sollten Sie einen Blick darauf werfenMann grep(kann überwältigend sein) undeinige Beispiele. Hier zunächst die Antwort:

Verwenden vongrep

grep "foobar" test.txt

sucht nach Zeilen mit dem Wort foobarin der Datei test.txtund zeigt alle Vorkommen an, während

grep "foo" -v "bar" test.txt

sucht nach Zeilen, die das Wort enthalten foo, aber nicht bar. Wir erhalten dies aufgrund von-vSchalter, für den die Manpage Folgendes erklärt:

-v, --invert-match
    Invert the sense of matching, to select non-matching lines.
    (-v is specified by POSIX .)

Es bedeutet einfach, dass nach Zeilen gesucht wird, die diese Wörter (hier bar) enthalten, diese aber in der endgültigen Anzeige ausschließt.Umkehrung der Suche.

Um die Anzahl der Zeilen zu zählen, die der Suche entsprechen, verwenden Sie-cschalten :

-c, --count
    Suppress normal output; instead print a count of matching lines
    for each input file. With the -v, --invert-match option (see below),
    count non-matching lines. (-c is specified by POSIX .)

Versuchen Sie als Selbstübung die grep-Suche in Dateienfoobar.

Die Antwort

Suche nach zu AB+CDignorierenden nonABund nonCDzu zählenden URLs:

grep "AB+CD" test | grep -cve "non"

wobei sowohl als auch -v "non"einfach ignoriert werden , da beide enthalten sind. Und gibt die Gesamtzahl der Übereinstimmungen an, anstatt sie auszudrucken. Um übereinstimmende Zeilen auszudrucken, ignorieren Sie einfach .nonABnonCDnon-c-c

Sie können es für einzelne Invertierungen verwenden:

grep "AB+CD" test | grep -cve "nonAB\|nonCD"

wobei entweder für oder \|steht ORund bedeutetnonABnonCD genauWort angegeben durch-eschalten.


Würde Ihnen raten,siehe Kamils ​​Antwort, lesen Sie so viele Manpages wie möglich (Sie kennen den Befehl), geben Sie sich beim Online-Recherchieren Mühe und unterstützen Sie die Community. Fügen Sie Ihrer Antwort gerne weitere Details hinzu.

verwandte Informationen