Welche Ausdrücke würden dem Muster (^[0-9]..[a-zA-Z ]+$) im Grep-Befehl entsprechen? Linux Bash

Welche Ausdrücke würden dem Muster (^[0-9]..[a-zA-Z ]+$) im Grep-Befehl entsprechen? Linux Bash

Ich versuche zu verstehen, welche Ausdrücke genau der reguläre Ausdruck (^[0-9]..[a-zA-Z ]+$)im Befehl erkennt grep(Linux-Terminal)

Ich weiß das, wenn ich den folgenden Befehl schreiben würde:

grep ^[0-9]..[a-zA-Z] filename.txt

Ich werde jede Zeile erkennen, die Ausdrücke wie enthält. 92afg Aber ich bin mir nicht sicher, was das +$bedeutet und welche Art von Ausdrücken ich mit dem Befehl erkennen kann.

grep ^[0-9]..[a-zA-Z]+$ filename.txt

Ich habe versucht, eine neue Textdatei zu öffnen und einfach Ausdrücke einzugeben, von denen ich dachte, dass sie erkannt würden, aber keiner davon stimmte überein. Daher wäre ich für eine Erklärung dankbar.

Antwort1

Lassen Sie uns das Ganze aufschlüsseln. Beachten Sie zunächst, dass dieser RegExp die"Erweiterter regulärer Ausdruck"Syntax (ERE) – das +ist ein Metazeichen, das in der Syntax „Einfacher regulärer Ausdruck“ nicht funktioniert, die grepstandardmäßig verwendet wird (was bedeutet, dass es mit sich selbst übereinstimmen würde und +an dieser Position ein Literal erfordern würde). Wenn Sie diesen regulären Ausdruck also mit verwenden möchten grep, müssen Sie die -EOption übergeben.

  • Dies ^ist ein Anker, der diese Position des regulären Ausdrucks mit dem Zeilenanfang verbindet.
  • Dies [0-9]ist eine Zeichenliste und entspricht jedem einzelnen (1) Zeichen, das in den Sortierbereich zwischen 0und fällt 9. Was genau das umfasst, hängt von der „Sortierreihenfolge“ ab, die unter anderem durch die Umgebungsvariable bestimmt wird LC_COLLATE.
  • Das .entspricht jedem einzelnen Zeichen, also ..bedeutet „zwei“ „beliebige zwei Zeichen“.
  • Das [a-zA-Z]ist wieder eine Zeichenliste und entspricht Zeichen (1) , die zwischen aund liegen, zsowie zusätzlich denen, die zwischen Aund liegen Z. Was das wiederum bedeutet, hängt von der Sortierreihenfolge ab!
  • Das +bedeutet „eines oder mehrere der vorherigen“
  • Dies $ist ein Anker, der diese Position des regulären Ausdrucks mit dem Ende der Zeile verbindet.

Ihr RegExist gedacht, um(1) entsprechen allen Zeilen, die

  • mit einer beliebigen Ziffer beginnen
  • gefolgt von zwei beliebigen Zeichen
  • und bis zum Zeilenende nur Buchstaben (aber mindestens einen) enthalten.

(1) Was es tatsächlich bewirken könnte, erfahren Sie weiter unten

Einige Notizen

  1. In Ihrem Beispiel verwenden Sie den regulären Ausdruck ohne Anführungszeichen. Das bedeutet, dass alle Zeichen von der Shell interpretiert werden können, bevor sie an den grepBefehl übergeben werden. Wenn Ihr Muster $Globbing-Zeichen ( *, ?und [...]Zeichenlisten!) enthält, versucht die Shell möglicherweise, eine Variablenerweiterung durchzuführen (und dabei Teile Ihres RegEx zu ersetzen) oder Globbing-Muster in möglicherweise mehrere Dateinamen zu erweitern, sodass Sie am Ende mehr Argumente in der Befehlszeile haben, als Sie ursprünglich beabsichtigt haben. Andere Zeichen, die für die Shell speziell sind ( >, #, ;und dergleichen), können zu noch unerwarteterem Verhalten führen. Sie sollten verwenden

    grep -E '^[0-9]..[a-zA-Z]+$' filename.txt
    

    stattdessen. Beachten Sie, dass Sie die öffnenden und schließenden Anker loswerden können, indem Sie das -xFlag verwenden, um eine Übereinstimmung für die ganze Zeile zu erzwingen:

    grep -x -E '[0-9]..[a-zA-Z]+' filename.txt
    
  2. Zeichenlisten mit Bereichen (wie a-z) sindgefährlichweil sie Ihnen vielleicht nicht das geben, was Sie denken. Naiv könnte man erwarten, dass sie alle Zeichen abgleichen, die zwischen dem Start- und Endzeichen in der ASCII-Tabelle liegen, aber das gilt nur für das CGebietsschema. In anderen Gebietsschemas (und insbesondere in den normalerweise eingestellten Systemgebietsschemas wie en_US.UTF-8) ist die Sortierreihenfolge etwa so, aAbB ... zZdass a-zauch die meisten Großbuchstaben übereinstimmen. Außerdem erfolgt die Übereinstimmung tatsächlich nicht auf der Ebene einzelner Zeichen, sondern auf der Ebene von „Sortierelementen“, was bedeutet, dass in einigen Gebietsschemas sogarKombinationen aus mehreren Buchstabenkann übereinstimmen (z. B. dzsin Ungarisch)! Siehediese Antwort(oder allgemein die meisten Antworten von @Stéphane Chazelas zum Thema Mustervergleich) für weitere Einblicke. Wenn Sie sicherstellen möchten, dass Ihre Bereiche funktionieren, legen Sie die Sortierreihenfolge zumindest für den angegebenen Befehl fest über

    LC_COLLATE="C" grep -E ' ... ' filename.txt
    

Antwort2

+steht für „eine oder mehrere Wiederholungen des vorherigen“, $ist „Zeilenende“. Beachten Sie den Unterschied gegenüber *„null oder mehr Wiederholungen“.

Es bedeutet also grundsätzlich: Jede Zeile, die mit einer Ziffer beginnt, gefolgt von zwei beliebigen Zeichen und anschließend einem oder mehreren (ggf. Groß-)Buchstaben¹ bis zum Zeilenende.

(¹ Vorsicht, in manchen Gebietsschemas sind möglicherweise nicht nur die 26 Buchstaben enthalten, die Sie in AZ oder az erwarten würden, z. B. èoder ŷje nach Sprache.)

Für eine gute Anleitung zu Regexes empfehle ich dringendGrymoires wunderschöne Website, das ich auch für zB sedund wärmstens empfehle awk.


Warum passt es nicht?

+ist Teil der erweiterten regulären Ausdrücke (und wird andernfalls als wörtliches +-Zeichen interpretiert).

Verwenden Sie also für die Verwendung +als „eine oder mehrere Wiederholungen“ das -EFlag -in grepund setzen Sie auch den regulären Ausdruck in Anführungszeichen, um Probleme mit Sonderzeichen der Shell zu vermeiden:

grep -E '^[0-9]..[a-zA-Z]+$' filename.txt

verwandte Informationen