2016-09-29 1 views
0

Ein Regex wie (?:(?=abc)|[abc])+ entspricht einem String, der aus a, b und c besteht, bis die Lookahead-Bedingung erfüllt ist. Zum Beispiel für die Zeichenfolge acbababcaaa wird es übereinstimmen acbab - Stoppen direkt vor der ersten abc, obwohl es bis zum Ende der Zeichenfolge vorrücken könnte, wenn es übermäßig gierig wäre.Lookahead-Verhalten in wiederholter Alternationsgruppe

Wir können dies erzwingen, indem wir $ an das Ende des Musters ((?:(?=abc)|[abc])+$) hinzufügen - jetzt stimmt es tatsächlich mit dem Ende der Zeichenfolge überein.

Wenn wir jetzt die Wiederholung zu posesive ((?:(?=abc)|[abc])++$) ändern - es wird bcaaa - also die erste Position, wo der Lookahead nicht mehr übereinstimmen kann.

Kann jemand die Gründe für diese Verhaltensweisen erklären?

+0

Die erste entspricht nur dem Beginn der Zeichenfolge, wenn kein globaler Suchmodus verwendet wird (siehe [demo] (https://regex101.com/r/t9zDtJ/1)), nicht 'abcab'. –

+0

@ WiktorStribiżew Sie sind offensichtlich richtig - ich hatte die falsche Zeichenfolge in Kopie + einfügen. Die Frage wurde aktualisiert. –

+0

Der Punkt hier glaube ich ist, dass in PCRE der Index nicht bewegt, wenn Sie eine * Null-Breite * haben. Beachten Sie, dass das Verhalten in JS anders ist, da JS-Regex den Regex-Index-Fortschritt nach einer Null-Breite-Übereinstimmung erzwingt. In einigen Situationen ist dieses Verhalten groß (wenn Sie aufeinanderfolgende Zero-Width- und Non-Zero-Width-Teilstrings abgleichen und - wie in diesem Fall - "Glitches" sein können. Im letzten Beispiel benötigt der Possessive-Quantor das Ende der Zeichenfolge direkt nach der Verzweigung übereinstimmt, so dass alle Null-Breite Übereinstimmungen die Übereinstimmung fehlschlagen, und Sie nur den letzten Chunk mit keine 'abc 'erhalten –

Antwort

1

Wenn Sie die Maschine zwingen, sich besitzergreifend zu bewegen, wird die erste Gruppe (?:...) nicht mehr zurückgesetzt.

Nach sehen abc mit dieser positiven Lookahead-Engine besteht aus der gesamten Gruppe und erwartet Ende der Eingabezeichenfolge $. Es ist nicht da und kann nicht zurückgehen, um die andere Seite des Alternation entweder zu versuchen, so dass es vollständig fehlschlägt und alle vorherigen verbrauchten Zeichen von [abc] freigegeben wird und Zeiger auf das nächste Zeichen der vorherigen Startposition des gesamten Musters zurückgesetzt wird.

Sie könnten es mit einer Atomgruppe (?>(?=abc)|[abc])+$ schreiben, um den Unterschied ausdrücklicher auszudrücken. Dieser Prozess wird fortgesetzt und schlägt jedes Mal fehl, wenn in der Eingabezeichenfolge eine abc angezeigt wird, auf die das Ende der Zeichenfolge $ nicht folgt.

Deshalb werden am Ende bcaaa Zeichen abgeglichen, da nach a keine positive Vorausschau erfolgt, bevor bcaaa verbraucht wird.

Verwandte Themen