web-dev-qa-db-de.com

Gierige versus widerstrebende versus besitzergreifende Quantifizierer

Ich fand dieses exzellentes Tutorial bei regulären Ausdrücken und während ich intuitiv verstehe, was "gierige", "widerstrebende" und "besitzergreifende" Quantifizierer tun, scheint es eine ernsthafte Lücke in meinem Verständnis zu geben.

Insbesondere im folgenden Beispiel:

Enter your regex: .*foo  // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.

Die Erklärung erwähnt das Essen der gesamten Eingabezeichenfolge, verbrauchte Buchstaben , Matcher Zurückziehen , rechtes Auftreten von "foo" wurde wieder auferlegt usw .

Leider verstehe ich trotz der Nizza-Metaphern immer noch nicht, was von wem gegessen wird ... Kennen Sie ein weiteres Tutorial, in dem (kurz und bündig) wie reguläre Ausdrücke funktionieren?

Wenn alternativ jemand den folgenden Absatz etwas anders formulieren kann, wäre dies sehr zu begrüßen:

Das erste Beispiel verwendet den gierigen Quantifizierer. *, Um "irgendetwas" zu finden, null oder mehrmals, gefolgt von den Buchstaben "f" "o" "o". Da der Quantifizierer gierig ist, frisst der. * -Teil des Ausdrucks zuerst die gesamte Eingabezeichenfolge. Zu diesem Zeitpunkt kann der Gesamtausdruck nicht erfolgreich sein, da die letzten drei Buchstaben ("f" "o" "o") bereits von wem verbraucht wurden (? ). Der Matcher zieht sich also langsam von rechts nach links zurück (? ), bis das Auftreten von "foo" ganz rechts wiederhergestellt wurde ( was bedeutet das? ), an welchem ​​Punkt die Übereinstimmung erfolgreich ist und die Suche endet.

Das zweite Beispiel widerstrebt jedoch, weshalb zunächst ( von wem? ) "nichts" konsumiert wird. Da "foo" nicht am Anfang der Zeichenfolge angezeigt wird, muss er den ersten Buchstaben (ein "x") schlucken ( wer schluckt?) ), wodurch die erste Übereinstimmung bei 0 und 4 ausgelöst wird. Unser Testkabel setzt den Vorgang fort, bis die Eingabezeichenfolge erschöpft ist. Es findet eine weitere Übereinstimmung bei 4 und 13.

Das dritte Beispiel findet keine Übereinstimmung, weil der Quantifizierer besitzergreifend ist. In diesem Fall wird die gesamte Eingabezeichenfolge von. * +, ( wie? belegt, und es bleibt nichts übrig, um das "foo" am Ende zu befriedigen des Ausdrucks. Verwenden Sie einen besitzergreifenden Quantifizierer für Situationen, in denen Sie alles erfassen möchten, ohne jemals zurückzutreten ( Was bedeutet Zurückzutreten? ); es wird den äquivalenten gierigen Quantifizierer in Fällen übertreffen, in denen die Übereinstimmung nicht sofort gefunden wird.

330
Regex Rookie

Ich versuche es mal.

Ein gieriger Quantifizierer passt zuerst so gut wie möglich. Also das .* entspricht der gesamten Zeichenfolge. Dann versucht der Matcher, die folgenden f zu finden, aber es sind keine Zeichen mehr vorhanden. Es wird also "zurückverfolgt", wodurch der gierige Quantifizierer mit einer Sache weniger übereinstimmt (wobei das "o" am Ende des Strings nicht übereinstimmt). Das stimmt immer noch nicht mit dem f im regulären Ausdruck überein, daher "rückverfolgt" es einen weiteren Schritt, wodurch der gierige Quantifizierer wieder mit einer Sache weniger übereinstimmt (wobei das "oo" am Ende des Strings nicht übereinstimmt). Das noch stimmt nicht mit dem f in der Regex überein, so dass es einen weiteren Schritt zurückverfolgt (wobei das "foo" am Ende verbleibt der Zeichenfolge nicht angepasst). Jetzt stimmt der Matcher schließlich mit dem f in der Regex überein, und der o und der nächste o stimmen ebenfalls überein. Erfolg!

Ein ngern oder "nicht gieriger" Quantifizierer passt zuerst so wenig wie möglich. Also das .* stimmt zunächst mit nichts überein, sodass die gesamte Zeichenfolge nicht übereinstimmt. Dann versucht der Matcher, die folgenden f zu finden, aber der nicht übereinstimmende Teil der Zeichenfolge beginnt mit "x", sodass dies nicht funktioniert. Der Matcher läuft also zurück und lässt den nicht-gierigen Quantifizierer noch eine weitere Übereinstimmung erkennen (jetzt stimmt er mit dem "x" überein, wobei "fooxxxxxxfoo" unerreicht bleibt). Dann wird versucht, das f zu finden, was erfolgreich ist, und das o und das nächste o im regulären Ausdruck stimmen ebenfalls überein. Erfolg!

In Ihrem Beispiel wird der Prozess dann mit dem verbleibenden nicht übereinstimmenden Teil der Zeichenfolge erneut gestartet, wobei derselbe Prozess ausgeführt wird.

Ein besitzergreifender Quantifizierer ist genau wie der gierige Quantifizierer, führt jedoch keine Rückschritte durch. Es beginnt also mit .* stimmt mit der gesamten Zeichenfolge überein und lässt nichts unübertroffen. Dann gibt es nichts mehr, was mit dem f in der Regex übereinstimmen könnte. Da der Possessive Quantifier nicht zurückverfolgt, schlägt die Übereinstimmung dort fehl.

454
Anomie

Es ist nur meine Übungsausgabe, die Szene zu visualisieren -

Visual Image

41
SIslam

Ich habe noch nie die genauen Begriffe "Aufstoßen" oder "Zurücktreten" gehört. Der Ausdruck, der diese ersetzen würde, ist "Backtracking", aber "Regurgitate" scheint ein ebenso guter Ausdruck zu sein wie jeder andere für "den Inhalt, der vor dem Backtracking vorläufig akzeptiert wurde und ihn wieder weggeworfen hat".

Das Wichtige an den meisten Regex-Engines ist, dass sie Backtracking: Sie vorläufig eine potenzielle teilweise Übereinstimmung akzeptieren, während sie versuchen, den gesamten Inhalt der Regex abzugleichen. Wenn die Regex beim ersten Versuch nicht vollständig zugeordnet werden kann, wird die Regex-Engine backtrack bei einer ihrer Übereinstimmungen. Es wird versucht, _*_, _+_, _?_, alternierend oder _{n,m}_ anders zu wiederholen und es erneut zu versuchen. (Und ja, dieser Vorgang kann lange dauern.)

Das erste Beispiel verwendet den gierigen Quantifizierer. *, Um "irgendetwas" zu finden, null oder mehrmals, gefolgt von den Buchstaben "f" "o" "o". Da der Quantifizierer gierig ist, frisst der. * -Teil des Ausdrucks zuerst die gesamte Eingabezeichenfolge. Zu diesem Zeitpunkt kann der Gesamtausdruck nicht erfolgreich sein, da die letzten drei Buchstaben ("f" "o" "o") bereits verbraucht wurden (von wem?).

Die letzten drei Buchstaben f, o und o wurden bereits vom anfänglichen Teil _.*_ der Regel verbraucht. Das nächste Element in der Regex, f, enthält jedoch nichts mehr in der Eingabezeichenfolge. Die Engine wird gezwungen, backtrack bei der anfänglichen Übereinstimmung _.*_ zu setzen und zu versuchen, alle bis auf das letzte Zeichen abzugleichen. (Es könnte sein, dass smart ​​und ein Backtrack zu all-but-the-last-three ist, da es drei wörtliche Begriffe enthält, mir sind jedoch keine Implementierungsdetails auf dieser Ebene bekannt.)

Der Matcher zieht sich also langsam zurück (von rechts nach links?), bis das Vorkommen von "foo" ganz rechts wieder unterdrückt wurde (was bedeutet das? =), bei denen

Dies bedeutet, dass foovorläufig bei der Suche nach _.*_ eingeschlossen wurde. Da dieser Versuch fehlgeschlagen ist, akzeptiert die Regex-Engine ein Zeichen weniger in _.*_. Wenn es in diesem Beispiel eine erfolgreiche Übereinstimmung gegeben hätte vor dem _.*_, würde die Engine wahrscheinlich versuchen, die _.*_-Übereinstimmung zu verkürzen (von rechts nach links, wie Sie gezeigt haben) out, weil es sich um ein gieriges Qualifikationsmerkmal handelt), und wenn es nicht in der Lage ist, die gesamten Eingaben abzugleichen, kann es sein, dass es gezwungen ist, die Übereinstimmungen vor the _.*_ in my neu zu bewerten hypothetisches Beispiel.

punkt ist das Match erfolgreich und die Suche endet.

Das zweite Beispiel widerstrebt jedoch, weshalb zunächst (von wem?) "nichts" konsumiert wird. Weil "foo"

Das anfängliche Nichts wird von _.?*_ verbraucht, wodurch die kürzestmögliche Menge von allem verbraucht wird, die es dem Rest des regulären Ausdrucks ermöglicht, zusammenzupassen.

erscheint nicht am Anfang der Zeichenkette, es ist gezwungen zu schlucken (wer schluckt?) die

Wiederum verbraucht der _.?*_ das erste Zeichen, nachdem der ursprüngliche Fehler, die gesamte Regex mit der kürzestmöglichen Übereinstimmung abzugleichen, zurückverfolgt wurde. (In diesem Fall erweitert die Regex-Engine die Übereinstimmung für _.*?_ von links nach rechts, da _.*?_ nur ungern möglich ist.)

erster Buchstabe (ein "x"), der die erste Übereinstimmung bei 0 und 4 auslöst. Unser Testkabel setzt den Vorgang fort, bis die Eingabezeichenfolge erschöpft ist. Es findet eine weitere Übereinstimmung bei 4 und 13.

Das dritte Beispiel findet keine Übereinstimmung, weil der Quantor besitzergreifend ist. In diesem Fall wird die gesamte Eingabezeichenfolge von. * +, (wie?) verbraucht.

Ein _.*+_ wird so viel wie möglich verbrauchen und wird nicht zurückverfolgt, um neue Übereinstimmungen zu finden, wenn der Regex als Ganzes keine Übereinstimmung findet. Da die Possessivform kein Backtracking durchführt, werden Sie wahrscheinlich nicht viele Verwendungen mit _.*+_ sehen, sondern mit Zeichenklassen oder ähnlichen Einschränkungen: _account: [[:digit:]]*+ phone: [[:digit:]]*+_.

Dies kann die Regex-Übereinstimmung drastisch beschleunigen, da Sie der Regex-Engine mitteilen, dass sie potenzielle Übereinstimmungen niemals rückgängig machen soll, wenn eine Eingabe nicht übereinstimmt. (Wenn Sie den gesamten übereinstimmenden Code von Hand schreiben müssten, wäre dies vergleichbar mit der Verwendung von putc(3), um ein eingegebenes Zeichen zurückzuschieben. Es wäre dem naiven Code sehr ähnlich, den Sie möglicherweise auf a schreiben.) Erster Versuch: Außer, dass Regex-Engines viel besser sind als ein einzelnes Push-Back-Zeichen, können sie alle zurück auf Null zurückspulen und es erneut versuchen. :)

Damit können Sie aber nicht nur potenzielle Beschleunigungen erzielen, sondern auch reguläre Ausdrücke schreiben, die genau den Anforderungen entsprechen, die Sie erfüllen müssen. Ich habe Probleme, ein einfaches Beispiel zu finden :), aber das Schreiben einer Regex mit Possessive-vs-Greedy-Quantifizierern kann zu unterschiedlichen Übereinstimmungen führen, und die eine oder andere kann geeigneter sein.

am Ende des Ausdrucks bleibt nichts übrig, um das "Foo" zu befriedigen. Verwenden Sie einen Possessivquantifizierer für Situationen, in denen Sie alles erfassen möchten, ohne jemals zurückzutreten (was bedeutet Zurückzutreten?); es wird übertreffen

"Zurückziehen" bedeutet in diesem Zusammenhang "Zurückziehen" - ein vorläufiger Teilabgleich wird verworfen, um einen anderen Teilabgleich zu versuchen, der möglicherweise erfolgreich ist oder nicht.

der äquivalente gierige Quantifizierer in Fällen, in denen die Übereinstimmung nicht sofort gefunden wird.

24
sarnold

http://swtch.com/~rsc/regexp/regexp1.html

Ich bin mir nicht sicher, ob das die beste Erklärung im Internet ist, aber es ist einigermaßen gut geschrieben und angemessen detailliert, und ich komme immer wieder darauf zurück. Vielleicht möchten Sie es ausprobieren.

Wenn Sie eine höhere Ebene (weniger ausführliche Erklärung) für einfache reguläre Ausdrücke wie den von Ihnen betrachteten wünschen, funktioniert eine reguläre Ausdrucks-Engine durch Zurückverfolgen. Im Wesentlichen wählt es einen Abschnitt der Zeichenfolge aus ("isst") und versucht, den regulären Ausdruck mit diesem Abschnitt abzugleichen. Wenn es passt, großartig. Wenn nicht, ändert die Engine die Auswahl des Abschnitts der Zeichenfolge und versucht, den regulären Ausdruck mit diesem Abschnitt abzugleichen, usw., bis jede mögliche Auswahl getroffen wurde.

Dieser Prozess wird rekursiv verwendet: Beim Versuch, einen String mit einem bestimmten regulären Ausdruck abzugleichen, teilt die Engine den regulären Ausdruck in Teile auf und wendet den Algorithmus auf jedes Teil einzeln an.

Der Unterschied zwischen gierigen, widerstrebenden und besitzergreifenden Quantifizierern tritt ein, wenn die Engine auswählt, mit welchem ​​Teil der Zeichenfolge sie übereinstimmen möchte, und wie diese Auswahl geändert wird, wenn sie beim ersten Mal nicht funktioniert. Die Regeln sind wie folgt:

  • Ein gieriger Quantifizierer weist die Engine an, mit der gesamten Zeichenfolge zu beginnen (oder zumindest mit der gesamten Zeichenfolge, die noch nicht mit vorherigen Teilen der übereinstimmt) regulärer Ausdruck) und prüfen Sie, ob er mit dem regulären Ausdruck übereinstimmt. Wenn ja, großartig; Die Engine kann mit dem Rest des regulären Ausdrucks fortfahren. Wenn nicht, wird es erneut versucht, aber ein Zeichen (das letzte) aus dem zu prüfenden Abschnitt der Zeichenfolge entfernt. Wenn das nicht funktioniert, schneidet es ein anderes Zeichen usw. ab. Ein gieriger Quantifizierer überprüft daher mögliche Übereinstimmungen in der Reihenfolge vom längsten zum kürzesten.

  • Ein widerstrebender Quantifizierer weist den Motor an, mit dem kürzestmöglichen Stück der Saite zu starten. Wenn es passt, kann der Motor weiterlaufen. Wenn nicht, fügt es dem Abschnitt der zu überprüfenden Zeichenfolge ein Zeichen hinzu und versucht dies usw., bis eine Übereinstimmung gefunden wird oder die gesamte Zeichenfolge übereinstimmt verbraucht. Ein widerstrebender Quantifizierer überprüft daher mögliche Übereinstimmungen in der Reihenfolge von der kürzesten zur längsten.

  • Ein Possessiv-Quantifizierer ist wie ein gieriger Quantifizierer beim ersten Versuch: Er weist die Engine an, durch Überprüfen des gesamten Strings zu starten. Der Unterschied ist, dass, wenn es nicht funktioniert, der Possessive Quantifier meldet, dass die Übereinstimmung sofort fehlgeschlagen ist. Die Engine ändert den betrachteten Abschnitt der Zeichenfolge nicht und unternimmt keine weiteren Versuche.

Dies ist der Grund, warum die Possessive-Quantifier-Übereinstimmung in Ihrem Beispiel fehlschlägt: Der .*+ Wird mit der gesamten Zeichenfolge verglichen, mit der er übereinstimmt. Anschließend sucht die Engine nach zusätzlichen Zeichen foo. aber natürlich findet es sie nicht, weil du schon am Ende der Zeichenkette bist. Wenn es ein gieriger Quantifizierer wäre, würde er zurückverfolgen und versuchen, den .* Nur bis zum vorletzten Zeichen, dann bis zum vorletzten Zeichen, dann bis zum viertletzten Zeichen, Das gelingt, weil erst dann ein foo übrig bleibt, nachdem .* den früheren Teil der Zeichenfolge "gefressen" hat.

19
David Z

Hier ist meine Einstellung unter Verwendung von Zellen- und Indexpositionen (siehe Abbildung hier , um eine Zelle von einem Index zu unterscheiden).

Gierig - Passen Sie so viel wie möglich an den gierigen Quantifikator und den gesamten regulären Ausdruck an. Wenn es keine Übereinstimmung gibt, fahren Sie mit dem gierigen Quantifizierer zurück.

Input String: xfooxxxxxxfoo
Regex:. * Foo

Das obige Regex besteht aus zwei Teilen:
(Ich und
(ii) "foo"

Jeder der folgenden Schritte analysiert die beiden Teile. Zusätzliche Kommentare für eine Übereinstimmung mit "Pass" oder "Fail" werden in geschweiften Klammern erklärt.

Schritt 1:
(i). * = xfooxxxxxxfoo - PASS ('. *' ist ein gieriger Quantifizierer und verwendet die gesamte Eingabezeichenfolge)
(ii) foo = Nach Index 13 ist kein passendes Zeichen mehr vorhanden - FAIL
Match fehlgeschlagen.

Schritt 2:
(i). * = xfooxxxxxxfo - PASS (Zurückverfolgen des gierigen Quantifizierers '. *')
(ii) foo = o - FAIL
Match fehlgeschlagen.

Schritt 3:
(i). * = xfooxxxxxxf - PASS (Zurückverfolgen des gierigen Quantifizierers '. *')
(ii) foo = oo - FAIL
Match fehlgeschlagen.

Schritt 4:
(i). * = xfooxxxxxx - PASS (Zurückverfolgen des gierigen Quantifizierers '. *')
(ii) foo = foo - PASS
Bericht MATCH

Ergebnis: 1 Treffer
Ich habe den Text "xfooxxxxxxfoo" gefunden, beginnend mit Index 0 und endend mit Index 13.

Unwillig - Passen Sie so wenig wie möglich an den unwilligen Quantifizierer an und passen Sie den gesamten regulären Ausdruck an. Wenn es keine Übereinstimmung gibt, fügen Sie dem widerstrebenden Quantifizierer Zeichen hinzu.

Input String: xfooxxxxxxfoo
Regex:. *? Foo

Der obige reguläre Ausdruck besteht aus zwei Teilen:
(ich) '.*?' und
(ii) "foo"

Schritt 1:
. *? = '' (leer) - PASS (Passen Sie so wenig wie möglich an den widerstrebenden Quantifizierer '. *?' an. Index 0 mit '' ist eine Übereinstimmung.)
foo = xfo - FAIL (Zelle 0,1,2 - d. h. Index zwischen 0 und 3)
Match fehlgeschlagen.

Schritt 2:
. *? = x - PASS (Fügen Sie dem widerstrebenden Quantifizierer '. *?' Zeichen hinzu. Zelle 0 mit 'x' ist eine Übereinstimmung.)
foo = foo - PASS
Bericht MATCH

Schritt 3:
. *? = '' (leer) - PASS (Passen Sie so wenig wie möglich an den widerstrebenden Quantifizierer '. *?' an. Index 4 mit '' ist eine Übereinstimmung.)
foo = xxx - FAIL (Zelle 4,5,6 - d. h. Index zwischen 4 und 7)
Match fehlgeschlagen.

Schritt 4:
. *? = x - PASS (Fügen Sie dem widerstrebenden Quantifizierer '. *?' Zeichen hinzu. Zelle 4.)
foo = xxx - FAIL (Zelle 5,6,7 - d. h. Index zwischen 5 und 8)
Match fehlgeschlagen.

Schritt 5:
. *? = xx - PASS (Fügen Sie Zeichen zum widerstrebenden Quantifizierer '. *?' hinzu. Zelle 4 bis 5.)
foo = xxx - FAIL (Zelle 6,7,8 - d. h. Index zwischen 6 und 9)
Match fehlgeschlagen.

Schritt 6:
. *? = xxx - PASS (Fügen Sie Zeichen zum widerstrebenden Quantifizierer '. *?' hinzu. Zelle 4 bis 6.)
foo = xxx - FAIL (Zelle 7,8,9 - d. h. Index zwischen 7 und 10)
Match fehlgeschlagen.

Schritt 7:
. *? = xxxx - PASS (Fügen Sie Zeichen zum widerstrebenden Quantifizierer '. *?' hinzu. Zelle 4 bis 7.)
foo = xxf - FAIL (Zelle 8,9,10 - d. h. Index zwischen 8 und 11)
Match fehlgeschlagen.

Schritt 8:
. *? = xxxxx - PASS (Fügen Sie Zeichen zum widerstrebenden Quantifizierer '. *?' hinzu. Zelle 4 bis 8.)
foo = xfo - FAIL (Zelle 9,10,11 - d. h. Index zwischen 9 und 12)
Match fehlgeschlagen.

Schritt 9:
. *? = xxxxxx - PASS (Fügen Sie Zeichen zum unwilligen Quantifizierer '. *?' hinzu. Zelle 4 bis 9.)
foo = foo - PASS (Zelle 10,11,12 - d. h. Index zwischen 10 und 13)
Bericht MATCH

Schritt 10:
. *? = '' (leer) - PASS (Passen Sie so wenig wie möglich an den widerstrebenden Quantifizierer '. *?' an. Index 13 ist leer.)
foo = Kein passendes Zeichen mehr vorhanden - FAIL (Nach Index 13 ist nichts mehr vorhanden)
Match fehlgeschlagen.

Ergebnis: 2 Treffer
Ich habe den Text "xfoo" gefunden, beginnend mit Index 0 und endend mit Index 4.
Ich habe den Text "xxxxxxfoo" gefunden, beginnend mit Index 4 und endend mit Index 13.

Possessive - Passen Sie so viel wie möglich an den Possessivquantifer an und passen Sie die gesamte Regex an. NICHT zurückverfolgen.

Input String: xfooxxxxxxfoo
Regex:. * + Foo

Der obige reguläre Ausdruck besteht aus zwei Teilen: '. * +' Und 'foo'.

Schritt 1:
. * + = xfooxxxxxxfoo - PASS (Passen Sie so viel wie möglich an den Possessive Quantifier '. *' an.)
foo = Kein Zeichen mehr vorhanden - FAIL (Keine Übereinstimmung nach Index 13)
Match fehlgeschlagen.

Hinweis: Backtracking ist nicht erlaubt.

Ergebnis: 0 Treffer

12
raka

Gierige Quantifizierung beinhaltet einen Mustervergleich unter Verwendung aller verbleibenden nicht validierten Zeichen eines Strings während einer Iteration. Nicht validierte Zeichen beginnen in der aktiven Sequenz . Jedes Mal, wenn keine Übereinstimmung gefunden wird, wird das Zeichen am Ende unter Quarantäne gestellt und die Prüfung wird erneut durchgeführt.

Wenn die aktive Sequenz nur die führenden Bedingungen des Regex-Musters erfüllt, wird versucht, die verbleibenden Bedingungen anhand der Quarantäne zu validieren. Wenn diese Validierung erfolgreich ist, werden übereinstimmende Zeichen in der Quarantäne validiert und verbleibende nicht übereinstimmende Zeichen bleiben nicht validiert und werden verwendet, wenn der Prozess bei der nächsten Iteration erneut beginnt.

Der Zeichenfluss erfolgt von der aktiven Sequenz in die Quarantäne. Das resultierende Verhalten ist, dass so viel wie möglich der ursprünglichen Sequenz in einem Match enthalten ist.

Reluctant Quantification entspricht größtenteils der gierigen Qualifikation, mit der Ausnahme, dass der Zeichenfluss umgekehrt ist - dh, sie beginnen in der Quarantäne und fließe in die aktive Sequenz . Das resultierende Verhalten ist, dass so wenig wie möglich von der ursprünglichen Sequenz in einem Match enthalten ist.

Possessive Quantification hat keine Quarantäne und enthält alles in einer festen aktiven Sequenz .

0

Gierig: "Finde die längste mögliche Folge von Zeichen"

Widerstrebend: "Übereinstimmung mit der kürzestmöglichen Zeichenfolge"

Possessive: Dies ist ein bisschen seltsam, da es NICHT (im Gegensatz zu gierig und ungern) versucht, eine Übereinstimmung für die gesamte Regex zu finden.

Übrigens: Keine Implementierung eines Regex-Pattern-Matchers wird jemals Backtracking verwenden. Alle echten Pattern Matcher sind extrem schnell - fast unabhängig von der Komplexität des regulären Ausdrucks!

0
Tilo Koerbs