Ich beobachte das folgende Verhalten von grep beim Ausführen fünfmal:

me@asus:~/go/src/company/topology-front$ lsof |grep "READ" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "README.md*" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "README.md" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "*README.md*" me@asus:~/go/src/company/topology-front$ lsof |grep "*README.md" me@asus:~/go/src/company/topology-front$ 

Ich konnte nicht verstehen, warum die letzten beiden Versuche von grep kein Ergebnis zurückgeben .

Antwort

grep Muster sind reguläre Ausdrücke (auch bekannt als Regex, Regexp, RE), grundlegende reguläre Ausdrücke (BRE), es sei denn, einer der -E / -F / -P / -K / -X Option (nur die ersten beiden sind Standard) wird verwendet.

* ist ein Regexp-Operator, der 0 oder mehr des vorhergehenden Atoms entspricht. Beispiel: d* entspricht 0 oder mehr d s. In BREs, wenn zu Beginn des Musters oder wenn Sie dem

oder \( Regexp-Operatoren, es entspricht nur einem Literal * (es wird auch verwendet) buchstäblich innerhalb von [...] Klammerausdrücken).

grep "*README.md*" stimmt also mit Zeilen überein, die ein Literal gefolgt von README gefolgt von einem einzelnen Zeichen (der Regexp-Operator .) gefolgt von m gefolgt von einer beliebigen Anzahl von d s. Da jede Zahl 0 enthält, entspricht dies funktional grep "*README.m" (was keinen Unterschied machen würde, welche Zeilen abgeglichen werden, nur auf dem, was abgeglichen werden kann innerhalb der Zeile (die beispielsweise mit der Option --color von GNU grep angezeigt wird).

Zum Beispiel würde es in diesen 2 Zeilen übereinstimmen:

*README mike ^^^^^^^^^ DONT***README-mddd ^^^^^^^^^^^^ 

(die ^ zeigen, was in der Zeile übereinstimmt durch den regulären Ausdruck, den Sie mit --color)

sehen konnten. Hier scheinen Sie reguläre Ausdrücke mit Shell-Platzhaltermustern zu verwechseln. Der Platzhalteroperator *, der mit 0 oder mehr Zeichen übereinstimmt, kann in regulären Ausdrücken .* geschrieben werden. Aber Folgendes zu tun:

grep ".*README\.md.*" 

wäre wieder dasselbe wie:

grep "README\.md" 

As grep sucht nach einer Übereinstimmung innerhalb innerhalb der Linie, anstatt Linien zu finden, die genau dem Muster entsprechen (für die Sie -x).

Mit ast-open grep, was auch ksh93 „s integriert (standardmäßig nicht immer integriert, und Sie müssen es aktivieren, indem Sie /opt/ast/bin vor $PATH) können Sie die Option -K für grep verwenden, um Shell-Platzhalter (erweiterte ksh93-Karten) zu verwenden. Mit dieser grep Implementierung können Sie Folgendes ausführen:

grep -K "README.md" 

oder

grep -xK "*README.md*" 

für Übereinstimmungen in Zeilen, die README.md enthalten.

Mit derselben Implementierung kann der Platzhalterabgleich auch für erweiterte (), augmented (-X) oder perlartig (-P) regulär Ausdrücke mit dem Operator (?K) (und \(?K\) in regulären Grundausdrücken, die die POSIX-Konformität tatsächlich brechen, sodass ich mich nicht darauf verlassen würde könnte in einer zukünftigen Version entfernt werden). Sie können also Folgendes tun:

grep -xE "(?K)*README.md*" 

dort.

Mit jeder modernen grep -Implementierung, Sie können auch Folgendes tun:

grep -F README.md 

Für eine Suche mit festen Zeichenfolgen (wobei . oben mit einem Literal . anstelle eines beliebigen Zeichens).

Kommentare

  • FWIW: Perl beschwert sich über * oder + zu Beginn des regulären Ausdrucks, ebenso wie grep -P
  • @ilkkachu Dies gilt auch für grep -E mit mehreren Implementierungen. Das *, das zu Beginn wörtlich behandelt wird, ist nur für BREs angegeben. Mit anderen REs, YMMV.
  • @St é phaneChazelas ' hat die Spezifikation für das führende Sternchen nicht gefunden . Ist es irgendwo dokumentiert? Ich ' verwende auch grep (oder grep -G).
  • @iBug, wenn Sie die Antwort genauer lesen, werden Sie ' bemerken, was (ich denke) Sie ' Bezieht sich auf ast-open ' s grep -K, das Shell-Muster verwendet (wobei * entspricht einer beliebigen Anzahl von Zeichen).
  • @iBug, wenn Sie meinen, dass * nichts Besonderes ist, wenn das erste Zeichen einer BRE angezeigt wird, siehe die POSIX-Spezifikation

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.