Suche…


Grundlegende Capture-Gruppen

Eine Gruppe ist ein Abschnitt eines regulären Ausdrucks in Klammern () . Dies wird üblicherweise als "Unterausdruck" bezeichnet und dient zwei Zwecken:

  • Sie macht den Unterausdruck atomar, dh er passt sich als Ganzes an, schlägt fehl oder wiederholt sich.
  • Der übereinstimmende Teil des Textes ist im Rest des Ausdrucks und im Rest des Programms verfügbar.

Gruppen werden in Regex-Engines nummeriert, beginnend mit 1. Die maximale Gruppennummer beträgt 9, aber viele moderne Regex-Varianten unterstützen höhere Gruppenzahlen. Gruppe 0 stimmt immer mit dem gesamten Muster überein, genauso wie die gesamte reguläre Ausdehnung mit Klammern.

Die Ordnungszahl erhöht sich mit jeder öffnenden Klammer, unabhängig davon, ob die Gruppen hintereinander angeordnet oder verschachtelt sind:

foo(bar(baz)?) (qux)+|(bla)
   1   2       3      4

Gruppen und ihre Anzahl

Nachdem ein Ausdruck eine Gesamtübereinstimmung erzielt hat, werden alle seine Gruppen verwendet - unabhängig davon, ob eine bestimmte Gruppe irgendetwas gefunden hat oder nicht.

Eine Gruppe kann optional sein, wie (baz)? oben oder in einem alternativen Teil des Ausdrucks, der nicht von der Übereinstimmung verwendet wurde, wie (bla) oben. In diesen Fällen enthalten nicht übereinstimmende Gruppen einfach keine Informationen.

Wenn ein Quantifizierer wie in (qux)+ oben hinter einer Gruppe platziert wird, (qux)+ die Gesamtzahl der Gruppen des Ausdrucks gleich. Wenn eine Gruppe mehr als einmal übereinstimmt, ist ihr Inhalt der letzte Treffer. Moderne Regex-Varianten erlauben jedoch den Zugriff auf alle Vorkommnisse.


Wenn Sie das Datum und die Fehlerstufe eines Protokolleintrags wie diesem abrufen möchten:

2012-06-06 12:12.014 ERROR: Failed to connect to remote end

Sie könnten so etwas verwenden:

^(\d{4}-\d{2}-\d{2}) \d{2}:\d{2}.\d{3} (\w*): .*$

Dies würde das Datum des Protokolleintrags 2012-06-06 als Erfassungsgruppe 1 und die Fehlerstufe ERROR als Erfassungsgruppe 2 extrahieren.

Rückreferenzen und nicht erfassende Gruppen

Da Groups "nummeriert" sind, unterstützen einige Engines auch das Übereinstimmen mit dem, was eine Gruppe zuvor wieder gefunden hat.

Angenommen, Sie wollten etwas finden, bei dem zwei gleiche Zeichenfolgen der Länge drei durch ein $ geteilt werden, das Sie verwenden würden:

(.{3})\$\1

Dies würde einer der folgenden Zeichenfolgen entsprechen:

"abc$abc"
"a b$a b"
"af $af "
"   $   "

Wenn Sie möchten, dass eine Gruppe nicht von der Engine nummeriert wird, können Sie sie für nicht erfassend festlegen. Eine nicht erfassende Gruppe sieht folgendermaßen aus:

(?:)

Sie sind besonders nützlich, um ein bestimmtes Muster beliebig oft zu wiederholen, da eine Gruppe auch als "Atom" verwendet werden kann. Erwägen:

(\d{4}(?:-\d{2}){2} \d{2}:\d{2}.\d{3}) (.*)[\r\n]+\1 \2

Dadurch werden zwei Protokolleinträge in den benachbarten Zeilen übereinstimmen, die denselben Zeitstempel und denselben Eintrag haben.

Benannte Erfassungsgruppen

Einige reguläre Ausdrucksvarianten ermöglichen benannte Erfassungsgruppen . Anstelle eines numerischen Index können Sie diese Gruppen im folgenden Code nach Namen referenzieren, dh in Rückverweisen, im Ersetzungsmuster sowie in den folgenden Zeilen des Programms.

Numerische Indizes ändern sich, wenn sich die Anzahl oder Anordnung von Gruppen in einem Ausdruck ändert, sodass sie im Vergleich spröder sind.

Um beispielsweise ein Wort ( \w+ ) in einfachen oder doppelten Anführungszeichen ( ['"] ) zu finden, können wir Folgendes verwenden:

(?<quote>['"])\w+\k{quote}

Welches ist äquivalent zu:

(['"])\w+\1

In einer einfachen Situation wie dieser hat eine normale, nummerierte Erfassungsgruppe keine Nachteile.

In komplexeren Situationen wird die Verwendung von benannten Gruppen die Struktur des Ausdrucks für den Leser deutlicher machen, was die Wartbarkeit verbessert.

Die Analyse von Protokolldateien ist ein Beispiel für eine komplexere Situation, die von Gruppennamen profitiert. Dies ist das Apache Common Log Format (CLF):

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326

Der folgende Ausdruck fängt die Teile in benannten Gruppen ein:

(?<ip>\S+) (?<logname>\S+) (?<user>\S+) (?<time>\[[^]]+\]) (?<request>"[^"]+") (?<status>\S+) (?<bytes>\S+)

Die Syntax hängt vom Flavour ab. Folgende sind üblich:

  • (?<name>...)
  • (?'name'...)
  • (?P<name>...)

Rückreferenzen:

  • \k<name>
  • \k{name}
  • \k'name'
  • \g{name}
  • (?P=name)

In der .NET-Variante können mehrere Gruppen denselben Namen haben. Sie verwenden Capture-Stapel .

In PCRE müssen Sie es explizit aktivieren, indem Sie den Modifizierer (?J) ( PCRE_DUPNAMES ) oder die PCRE_DUPNAMES (?|) Verwenden. Es ist jedoch nur der zuletzt erfasste Wert verfügbar.

(?J)(?<a>...)(?<a>...)
(?|(?<a>...)|(?<a>...))


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow