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+CD
ohne nonAB
und 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 -v
folgendermaß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:
Zeilen mit
foo
Pluszeichen, Zeilen mitbar
(foo OR bar
):grep -e foo -e bar
Zeilen, die
foo
undbar
in der gleichen Zeile enthalten (foo AND bar
):grep foo | grep bar
Zeilen, die keine
baz
(NOT baz
) enthalten:grep -v baz
Mit diesen Bausteinen können Sie Ihre Logik aufbauen. Das Problem ist, -v
dass 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 bar
mit einemeinzel(erweitert) grep
:
Wiederum Zeilen, die
foo
undbar
in 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+CD
ohnenonAB
undnonCD
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+CD
das 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 foobar
in der Datei test.txt
und 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-v
Schalter, 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-c
schalten :
-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+CD
ignorierenden nonAB
und nonCD
zu 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 .nonAB
nonCD
non
-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 OR
und bedeutetnonAB
nonCD
genauWort angegeben durch-e
schalten.
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.