Regex Lookahead, Lookbehind und Atomgruppen

314

Ich habe diese Dinge in meinem Regex-Körper gefunden, aber ich habe keine Ahnung, wofür ich sie verwenden kann. Hat jemand Beispiele, damit ich versuchen kann zu verstehen, wie sie funktionieren?

(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind

(?>) - atomic group
Spidfire
quelle
18
Warum hat die Regex-Website keine einfache Tabelle wie diese? Stattdessen haben sie nur Textblöcke, die erklären. reguläre-
Ausdrücke.info/
3
@ Whitecat Versuchen Sie: regex101.com regexr.com
Andrew

Antworten:

848

Beispiele

Angesichts der Zeichenfolge foobarbarfoo:

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

Sie können sie auch kombinieren:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

Definitionen

Schauen Sie positiv nach vorne (?=)

Finden Sie Ausdruck A, wobei Ausdruck B folgt:

A(?=B)

Schau voraus negativ (?!)

Suchen Sie Ausdruck A, wobei Ausdruck B nicht folgt:

A(?!B)

Schau hinter positiv (?<=)

Suchen Sie Ausdruck A, wobei Ausdruck B vorangestellt ist:

(?<=B)A

Schau hinter das Negative (?<!)

Suchen Sie Ausdruck A, wobei Ausdruck B nicht vorangestellt ist:

(?<!B)A

Atomgruppen (?>)

Eine Atomgruppe verlässt eine Gruppe und wirft alternative Muster nach dem ersten übereinstimmenden Muster innerhalb der Gruppe weg (Backtracking ist deaktiviert).

  • (?>foo|foot)sangewendet auf entspricht footsder ersten Alternative foo, sschlägt dann fehl, da dies nicht unmittelbar folgt, und stoppt, wenn das Zurückverfolgen deaktiviert ist

Eine nichtatomare Gruppe ermöglicht das Zurückverfolgen. Wenn der nachfolgende Abgleich fehlschlägt, werden alternative Muster zurückverfolgt und verwendet, bis eine Übereinstimmung für den gesamten Ausdruck gefunden wird oder alle Möglichkeiten ausgeschöpft sind.

  • (foo|foot)sangewendet auf footsWillen:

    1. Passen Sie die erste Alternative an foo, schlagen Sie dann fehl, da sdies nicht unmittelbar folgt foots, und kehren Sie zur zweiten Alternative zurück.
    2. Match seine 2. Alternative foot, dann erfolgreich wie ssofort folgt foots, und stoppen.

Einige Ressourcen

Online-Tester

Himmelfuß
quelle
1
Was meinst du mit "findet den zweiten Takt" Teil? Der Ausdruck / die Zeichenfolge enthält nur einen Balken. Danke
zickig
2
@ziggy die getestete Saite ist "foobarbarfoo". Wie Sie sehen können, gibt es zwei foo und zwei Balken in der Zeichenfolge.
Skyfoot
4
Kann jemand erklären, wann man eine Atomgruppe braucht? Wenn ich nur mit der ersten Alternative übereinstimmen muss, warum sollte ich dann mehrere Alternativen angeben?
Arviman
2
Bessere Erklärung zur Atomgruppe bei dieser Antwort . Kann jemand hier bearbeiten, um diese didatische Antwort zu vervollständigen?
Peter Krauss
5
Nur eine Anmerkung, dass diese Antwort wichtig war, als ich zu einem Projekt kam, das ernsthafte Regex-Chops erforderte. Dies ist eine ausgezeichnete, prägnante Erklärung für das Umsehen.
Tom Coughlin
215

Lookarounds sind Zusicherungen mit einer Breite von Null. Sie suchen nach einem regulären Ausdruck (rechts oder links von der aktuellen Position - basierend auf vorne oder hinten), sind erfolgreich oder scheitern, wenn eine Übereinstimmung gefunden wird (basierend darauf, ob sie positiv oder negativ ist) und verwerfen den übereinstimmenden Teil. Sie verbrauchen kein Zeichen - die Übereinstimmung mit dem ihnen folgenden regulären Ausdruck (falls vorhanden) beginnt an derselben Cursorposition.

Lesen Sie regelmäßig-expression.info für weitere Details.

  • Positiver Lookahead:

Syntax:

(?=REGEX_1)REGEX_2

Nur übereinstimmen, wenn REGEX_1 übereinstimmt; Nach dem Abgleich von REGEX_1 wird der Abgleich verworfen und die Suche nach REGEX_2 beginnt an derselben Position.

Beispiel:

(?=[a-z0-9]{4}$)[a-z]{1,2}[0-9]{2,3}

REGEX_1 [a-z0-9]{4}$entspricht vier alphanumerischen Zeichen, gefolgt vom Zeilenende.
REGEX_2 [a-z]{1,2}[0-9]{2,3}entspricht einem oder zwei Buchstaben, gefolgt von zwei oder drei Ziffern.

REGEX_1 stellt sicher, dass die Länge der Zeichenfolge zwar 4 beträgt, verbraucht jedoch keine Zeichen, sodass die Suche nach REGEX_2 an derselben Stelle beginnt. Jetzt stellt REGEX_2 sicher, dass die Zeichenfolge mit einigen anderen Regeln übereinstimmt. Ohne Vorausschau würde es zu Saiten mit einer Länge von drei oder fünf passen.

  • Negativer Lookahead

Syntax:

(?!REGEX_1)REGEX_2

Nur übereinstimmen, wenn REGEX_1 nicht übereinstimmt. Nach Überprüfung von REGEX_1 beginnt die Suche nach REGEX_2 an derselben Position.

Beispiel:

(?!.*\bFWORD\b)\w{10,30}$

Der Look-Ahead-Teil sucht nach dem FWORDin der Zeichenfolge und schlägt fehl, wenn er es findet. Wenn es nicht gefunden wird FWORD, ist die Vorausschau erfolgreich und der folgende Teil überprüft, ob die Länge der Zeichenfolge zwischen 10 und 30 liegt und nur Wortzeichen enthälta-zA-Z0-9_

Look-Behind ähnelt Look-Ahead: Es schaut nur hinter die aktuelle Cursorposition. Einige Regex-Varianten wie Javascript unterstützen keine Behind-Behind-Behauptungen. Und die meisten Varianten, die dies unterstützen (PHP, Python usw.), erfordern, dass dieser Look-Behind-Teil eine feste Länge hat.

  • Atomgruppen verwerfen / vergessen grundsätzlich die nachfolgenden Token in der Gruppe, sobald ein Token übereinstimmt. Auf dieser Seite finden Sie Beispiele für Atomgruppen
Amarghosh
quelle
Nach Ihrer Erklärung scheint dies nicht in Javascript zu funktionieren. /(?=source)hello/.exec("source...hummhellosource ") = null. Ist deine Erklärung richtig?
Helin Wang
@HelinWang Diese Erklärung ist richtig. Ihre Regex erwartet eine Zeichenfolge, die gleichzeitig Quelle und Hallo ist!
Amarghosh
@jddxf Möchtest du das näher erläutern?
Amarghosh
@Amarghosh Ich stimme zu "Sie suchen nach einem regulären Ausdruck (rechts oder links von der aktuellen Position - basierend auf vorne oder hinten), sind erfolgreich oder scheitern, wenn eine Übereinstimmung gefunden wird (basierend darauf, ob sie positiv oder negativ ist) und verwerfen die Übereinstimmung Portion.". Lookahead sollte also nach einem
regulären Ausdruck
@Amarghosh würde (?=REGEX_1)REGEX_2passen nur , wenn REGEX_2kommt nach REGEX_1 ?
Aandis
0

Grokking Lookaround schnell.
Wie kann man Lookahead und Lookbehind unterscheiden? Nehmen Sie 2 Minuten Tour mit mir:

(?=) - positive lookahead
(?<=) - positive lookbehind

Annehmen

    A  B  C #in a line

Nun fragen wir B: Wo bist du?
B hat zwei Lösungen, um den Standort zu deklarieren:

Eins, B hat A vor und hat C vor
Zwei, B ist vor (Lookahead) vor C und hinter (Lookhehind) A.

Wie wir sehen können, sind das Hin und Her in beiden Lösungen gegensätzlich.
Regex ist Lösung Zwei.

Infinitesimalrechnung
quelle