it-swarm.com.de

Wie starte ich grep mit mehreren UND-Mustern?

Ich möchte die Übereinstimmung mit mehreren Mustern mit implizitem UND zwischen Mustern erhalten, d. H. Entspricht dem Ausführen mehrerer Greps in einer Sequenz:

grep pattern1 | grep pattern2 | ...

Wie kann man es in so etwas umwandeln?

grep pattern1 & pattern2 & pattern3

Ich möchte Single Grep verwenden, da ich Argumente dynamisch erstelle, sodass alles in eine Zeichenfolge passen muss. Die Verwendung des Filters ist eine Systemfunktion, keine grep, daher kein Argument dafür.


Verwechseln Sie diese Frage nicht mit:

grep "pattern1\|pattern2\|..."

Dies ist eine ODER Multi-Pattern-Übereinstimmung.

91
greenoldman

agrep kann dies mit folgender Syntax tun:

agrep 'pattern1;pattern2'

Mit GNU grep können Sie bei Erstellung mit PCRE-Unterstützung Folgendes tun:

grep -P '^(?=.*pattern1)(?=.*pattern2)'

Mit ast grep :

grep -X '.*pattern1.*&.*pattern2.*'

(Hinzufügen von .*s as <x>&<y> stimmt mit Zeichenfolgen überein, die mit beiden übereinstimmen <x> und <y> genau , a&b würde niemals übereinstimmen, da es keinen solchen String gibt, der gleichzeitig a und b sein kann) .

Wenn sich die Muster nicht überlappen, können Sie möglicherweise auch Folgendes tun:

grep -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'

Der beste tragbare Weg ist wahrscheinlich mit awk wie bereits erwähnt:

awk '/pattern1/ && /pattern2/'

Mit sed:

sed -e '/pattern1/!d' -e '/pattern2/!d'

Bitte beachten Sie, dass alle diese eine andere Syntax für reguläre Ausdrücke haben.

85

Sie haben keine grep-Version angegeben, dies ist wichtig. Einige Regexp-Engines ermöglichen mehrere Übereinstimmungen, die von AND mit '&' unterstützt werden. Dies ist jedoch keine Standard- und nicht portable Funktion. Aber zumindest GNU grep unterstützt dies nicht.

OTOH Sie können grep einfach durch sed, awk, Perl usw. ersetzen (in der Reihenfolge der Gewichtszunahme aufgeführt). Mit awk würde der Befehl so aussehen

 Awk '/ regexp1/&&/regexp2/&&/regexp3/{print; } '

und es kann so konstruiert werden, dass es auf einfache Weise in der Befehlszeile angegeben wird.

19
Netch

Dies ist keine sehr gute Lösung, zeigt aber einen etwas coolen "Trick"

function chained-grep {
    local pattern="$1"
    if [[ -z "$pattern" ]]; then
        cat
        return
    fi    

    shift
    grep -- "$pattern" | chained-grep "[email protected]"
}

cat something | chained-grep all patterns must match order but matter dont
8
olejorgenb

Wenn patterns ein Muster pro Zeile enthält, können Sie Folgendes tun:

awk 'NR==FNR{a[$0];next}{for(i in a)if($0!~i)next}1' patterns -

Oder dies entspricht Teilzeichenfolgen anstelle von regulären Ausdrücken:

awk 'NR==FNR{a[$0];next}{for(i in a)if(!index($0,i))next}1' patterns -

Um alle statt keiner Zeilen der Eingabe zu drucken, falls patterns leer ist, ersetzen Sie NR==FNR mit FILENAME==ARGV[1], oder mit ARGIND==1 in gawk.

Diese Funktionen drucken die Zeilen von STDIN, die jede als Argument angegebene Zeichenfolge als Teilzeichenfolge enthalten. ga steht für grep all und gai ignoriert Groß- und Kleinschreibung.

ga(){ awk 'FILENAME==ARGV[1]{a[$0];next}{for(i in a)if(!index($0,i))next}1' <(printf %s\\n "[email protected]") -; }
gai(){ awk 'FILENAME==ARGV[1]{a[tolower($0)];next}{for(i in a)if(!index(tolower($0),i))next}1' <(printf %s\\n "[email protected]") -; }
7
nisetama

git grep

Hier ist die Syntax mit git grep Kombinieren mehrerer Muster mit Booleschen Ausdrücken:

git grep --no-index -e pattern1 --and -e pattern2 --and -e pattern3

Mit dem obigen Befehl werden Zeilen gedruckt, die mit allen Mustern gleichzeitig übereinstimmen.

--no-index Suchen Sie nach Dateien im aktuellen Verzeichnis, die nicht von Git verwaltet werden.

Prüfen man git-grep für Hilfe.

Siehe auch:

Informationen zum Betrieb von [~ # ~] oder [~ # ~] finden Sie unter:

4
kenorb

Hier ist meine Einstellung, und dies funktioniert für Wörter in mehreren Zeilen:

Verwenden find . -type f gefolgt von ebenso vielen
-exec grep -q 'first_Word' {} \;
und das letzte Schlüsselwort mit
-exec grep -l 'nth_Word' {} \;

-q leise/leise
-l Dateien mit Übereinstimmungen anzeigen

Die folgende Liste enthält Dateinamen mit den Wörtern "Kaninchen" und "Loch":
find . -type f -exec grep -q 'rabbit' {} \; -exec grep -l 'hole' {} \;

2
StackRover

ripgrep

Hier ist das Beispiel mit rg :

rg -N '(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)' file.txt

Es ist eines der schnellsten Grepping-Tools, da es auf Rusts Regex-Engine basiert, das endliche Automaten, SIMD und aggressive Literal-Optimierungen verwendet, um die Suche sehr schnell zu machen.

Siehe auch zugehörige Funktionsanforderung unter GH-875 .

1
kenorb

Dieser Shell-Befehl kann helfen:

eval "</dev/stdin $(printf "|grep '%s'" pattern1 pattern2)" FILE

Es ist jedoch einfacher, wenn alle Ihre Muster in der Datei gespeichert sind, sodass Sie den folgenden Alias ​​definieren können:

alias grep-all="cat $(xargs printf '| grep "%s"' < patterns.txt)"

und benutze es als:

cat text.txt | grep-all

Sie können den Alias ​​natürlich abhängig von Ihrer erforderlichen Syntax ändern. Mit diesem Alias:

alias grep-all="</dev/stdin $(xargs printf '|grep "%s"' < patterns.txt)"

sie können nur einen einzigen Befehl verwenden, z.

grep-all text.txt

Weitere Ideen finden Sie auch unter: Alle Muster aus der Datei gleichzeitig abgleichen .

Informationen zur UND-Verknüpfung pro Datei finden Sie unter: Überprüfen Sie, ob alle Zeichenfolgen oder regulären Ausdrücke in einer Datei vorhanden sind. .

1
kenorb