An und Ausdrücke mit grep benötigen Sie zwei Aufrufe:
grep -Ei "search term" | grep -Eiv "exclude term"
Wenn die Begriffe, nach denen Sie suchen, keine regulären Ausdrücke sind, verwenden Sie den festen Zeichenfolgenabgleich (-F
), was schneller ist:
grep -F "search term" | grep -Fv "exclude term"
Abgesehen davon, grep zweimal aufzurufen, fällt mir nur eine Möglichkeit ein, dies zu erreichen. Es beinhaltet Perl-kompatible reguläre Ausdrücke (PCRE) und einige ziemlich hackige Look-Around-Assertionen.
Um nach foo zu suchen ausgenommen Übereinstimmungen, die bar enthalten , können Sie Folgendes verwenden:
grep -P '(?=^((?!bar).)*$)foo'
So funktioniert es:
-
(?!bar)
entspricht allem, was nicht bar ist ohne Zeichen aus der Zeichenfolge zu verbrauchen. Dann.
verbraucht ein einzelnes Zeichen. -
^((?!bar).)*
wiederholt das Obige vom Anfang der Zeichenfolge (^
) bis zum Ende ($
). Es schlägt fehl, wennbar
seit(?!bar)
an einem beliebigen Punkt angetroffen wird stimmt nicht überein. -
(?=^((?!bar).)*$)
stellt sicher, dass die Zeichenfolge mit dem vorherigen Muster übereinstimmt, ohne Zeichen aus der Zeichenfolge zu verbrauchen. -
foo
sucht nach foo wie gewohnt.
Ich habe diesen Hack in Regulärer Ausdruck gefunden, um eine Zeichenfolge abzugleichen, die kein Wort enthält?. In der Antwort von Bart Kiers finden Sie eine viel detailliertere Erklärung, wie die negative Vorausschau funktioniert.
Wenn Sie dies in einem Durchgang tun möchten, können Sie awk anstelle von grep verwenden.
Format:
echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'
Beispiele:
echo "hello there" | awk '/hello/ && !/there/'
Gibt nichts zurück.
echo "hello thre" | awk '/hello/ && !/there/'
Gibt zurück:hallo drei
echo "hllo there" | awk '/hello/ && !/there/'
Gibt nichts zurück.
Für mehrere Muster können Sie Klammern verwenden, um sie zu gruppieren.
Beispiele:
echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'
Gibt zurück:hallo drei
echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'
Gibt zurück:hallo drei
echo "hello there" | awk '(/hello/ || /hi/) && !/there/'
Gibt nichts zurück.
echo "hi there" | awk '(/hello/ || /hi/) && !/there/'
Gibt nichts zurück.