Auf gierig gegen nicht gierig
Die Wiederholung in Regex ist standardmäßig gierig : Sie versuchen, so viele Wiederholungen wie möglich abzugleichen. Wenn dies nicht funktioniert und sie zurückverfolgen müssen, versuchen sie, jeweils eine Wiederholung weniger abzugleichen, bis eine Übereinstimmung des gesamten Musters vorliegt gefunden. Wenn ein Match schließlich stattfindet, würde eine gierige Wiederholung so vielen Wiederholungen wie möglich entsprechen.
Der ?
als Wiederholungsquantifizierer ändert dieses Verhalten in nicht gierig , auch widerstrebend genannt ( in z. B. Java ) (und manchmal "faul"). Im Gegensatz dazu wird bei dieser Wiederholung zunächst versucht, so wenig Wiederholungen wie möglich zuzuordnen. Wenn dies nicht funktioniert und sie zurückverfolgen müssen, beginnen sie, jeweils eine weitere Wiederholung abzugleichen. Wenn ein Match schließlich stattfindet, würde eine widerstrebende Wiederholung so wenig Wiederholungen wie möglich entsprechen.
Verweise
Beispiel 1: Von A bis Z.
Vergleichen wir diese beiden Muster: A.*Z
und A.*?Z
.
Angesichts der folgenden Eingabe:
eeeAiiZuuuuAoooZeeee
Die Muster ergeben die folgenden Übereinstimmungen:
Konzentrieren wir uns zunächst auf das, was A.*Z
tut. Wenn es mit dem ersten übereinstimmt , versucht A
der .*
, der gierig ist, zuerst so viele .
wie möglich zu finden.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
Da das Z
nicht übereinstimmt, fährt der Motor zurück und .*
muss dann eins weniger übereinstimmen .
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
Dies passiert noch einige Male, bis wir schließlich dazu kommen:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
Jetzt Z
kann übereinstimmen, so dass das Gesamtmuster übereinstimmt:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
Im Gegensatz dazu entspricht die widerstrebende Wiederholung in den A.*?Z
ersten Spielen so wenig .
wie möglich und nimmt dann mehr .
als nötig. Dies erklärt, warum in der Eingabe zwei Übereinstimmungen gefunden werden.
Hier ist eine visuelle Darstellung der Übereinstimmung der beiden Muster:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
Beispiel: Eine Alternative
In vielen Anwendungen sind die beiden Übereinstimmungen in der obigen Eingabe erwünscht, daher .*?
wird anstelle der Gier eine Zurückhaltung verwendet .*
, um eine Überanpassung zu verhindern. Für dieses spezielle Muster gibt es jedoch eine bessere Alternative, wenn eine negierte Zeichenklasse verwendet wird.
Das Muster A[^Z]*Z
findet auch die gleichen zwei Übereinstimmungen wie das A.*?Z
Muster für die obige Eingabe ( wie auf ideone.com zu sehen ). [^Z]
wird als negierte Zeichenklasse bezeichnet : Sie passt zu allem anderen Z
.
Der Hauptunterschied zwischen den beiden Mustern besteht in der Leistung: Da die negierte Zeichenklasse strenger ist, kann sie für eine bestimmte Eingabe nur in eine Richtung übereinstimmen. Es spielt keine Rolle, ob Sie für dieses Muster einen gierigen oder widerstrebenden Modifikator verwenden. In einigen Geschmacksrichtungen können Sie sogar noch bessere Ergebnisse erzielen und einen sogenannten Possessiv-Quantifizierer verwenden, der überhaupt nicht zurückverfolgt.
Verweise
Beispiel 2: Von A nach ZZ
Dieses Beispiel sollte veranschaulichend sein: Es zeigt, wie die gierigen, widerstrebenden und negierten Zeichenklassenmuster bei gleicher Eingabe unterschiedlich übereinstimmen.
eeAiiZooAuuZZeeeZZfff
Dies sind die Übereinstimmungen für die obige Eingabe:
Hier ist eine visuelle Darstellung dessen, was sie übereinstimmten:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
verwandte Themen
Hierbei handelt es sich um Links zu Fragen und Antworten zum Stapelüberlauf, die einige Themen abdecken, die möglicherweise von Interesse sind.
Eine gierige Wiederholung kann eine andere übertreffen