Gierige und faule Quantoren
Gierige und faule Quantoren in JavaScript-Regulärausdrücken: Greedy nimmt das Maximum und geht zurück, Lazy (*?, +?, ??, {n,m}?) nimmt das Minimum.
Ein Quantor wie *, + oder ? gibt einem regulären Ausdruck vor, wie oft das vorangehende Muster wiederholt werden darf. Wenn jedoch mehrere unterschiedlich lange Textpassagen das Muster erfüllen würden, muss die Engine entscheiden, welche sie auswählt. Genau diese Entscheidung steuern gierige und faule Quantoren.
Standardmäßig ist jeder Quantor gierig: Er nimmt so viele Zeichen wie möglich. Fügt man nach dem Quantor ein ? hinzu, wird er faul: Er nimmt so wenige Zeichen wie möglich. Die falsche Wahl ist einer der häufigsten Regex-Fehler — das klassische Symptom ist ein Muster, das „zu viel matched". Diese Seite erklärt den Mechanismus beider Modi, damit Sie bewusst den richtigen einsetzen können.
Wie gieriges Matching wirklich funktioniert: Konsumieren, dann Backtracking
Ein gieriger Quantor weiß nicht magisch, wo er aufhören soll. Er arbeitet in zwei Phasen:
- Maximales Konsumieren.
.*verschluckt zunächst den gesamten restlichen String. - Backtracking. Wenn das nachfolgende Muster nicht mehr matchen kann (weil alles bereits verbraucht ist), gibt die Engine Zeichen einzeln zurück und wiederholt den Versuch nach jedem Schritt, bis das gesamte Muster passt.
Gierig bedeutet also: „Nimm alles, und gib dann widerwillig so wenig wie nötig zurück, damit der Rest des Musters passt." Das Backtracking-Schritt zu verstehen ist der Schlüssel, um vorherzusagen, was gierige Muster tun.
Gieriges * in der Praxis
Hier matcht .* beliebige Zeichen null oder mehr Male. Da danach nichts mehr erforderlich ist, wird kein Backtracking benötigt und der Quantor behält alles bis zum Zeilenende — Ergebnis: "ABCD*E".
Gieriges + in der Praxis
C+ matcht "C" ein oder mehr Male und nimmt gierig alle drei, der Match ist daher "ABCCC".
Wie faules Matching funktioniert: Minimum konsumieren, dann ausweiten
Ein fauler Quantor kehrt die Strategie um:
- Minimales Konsumieren.
.*?beginnt damit, nichts zu matchen. - Ausweiten. Nur wenn der Rest des Musters nicht passt, lässt die Engine den faulen Quantor ein weiteres Zeichen nehmen und wiederholt dann den Versuch — solange, bis das gesamte Muster erfüllt ist.
Faul bedeutet also: „Nimm so wenig wie möglich und wachse nur, wenn du dazu gezwungen bist." Man macht jeden Quantor faul, indem man ? anhängt.
Faules *? in der Praxis
Dies ist der verwirrende Fall. Das Ergebnis ist lediglich "AB". Warum? Weil .*? erlaubt ist, nichts zu matchen, und im Muster danach nichts steht, das weiteres Konsumieren erzwingt. Sobald AB matcht, ist das Muster bereits vollständig, sodass der faule Quantor zufrieden bei null Zeichen stoppt. Ein fauler Quantor weitet sich nur aus, wenn etwas nach ihm — ein Trennzeichen, ein Literal oder ein Anker — es verlangt.
Faules +? in der Praxis
C+? muss mindestens ein "C" matchen (das verlangt +), und nichts danach fordert mehr, sodass er beim ersten stoppt: "ABC".
Das klassische Beispiel: <.*> vs. <.*?>
Der Unterschied zwischen gierig und faul lässt sich am besten erkennen, wenn nach dem Quantor noch etwas steht. Das Matchen von HTML-Tags ist das Lehrbuchbeispiel. Beide Muster auf denselben String anwenden:
- Gieriges
/<.*>/matcht"<p>Hello</p>"— den gesamten String..*nimmt alles und macht dann nur so viel Backtracking, dass ein>für das abschließende>im Muster übrig bleibt — und landet beim letzten>. - Faules
/<.*?>/matcht nur"<p>"— einen einzelnen Tag..*?weitet sich Zeichen für Zeichen aus und stoppt sofort beim ersten>.
Wenn das Ziel „einen Tag matchen", „einen in Anführungszeichen stehenden String matchen" oder „bis zum nächsten Trennzeichen matchen" lautet, ist faul fast immer die richtige Wahl.
Die vollständige Familie der faulen Quantoren
Jeder gierige Quantor hat ein faules Pendant, das durch Anhängen von ? gebildet wird:
| Gierig | Faul | Bedeutung der faulen Form |
|---|---|---|
* | *? | Null oder mehr, so wenige wie möglich |
+ | +? | Ein oder mehr, so wenige wie möglich |
? | ?? | Null oder eins, bevorzuge null |
{2,5} | {2,5}? | Zwischen 2 und 5, bevorzuge 2 |
{2,} | {2,}? | Mindestens 2, bevorzuge 2 |
?? ist kein Tippfehler: Das erste ? ist der Quantor (null oder eins) und das zweite macht ihn faul, sodass er es bevorzugt, nichts zu matchen, wenn er die Wahl hat.
Wann sollte man faule Quantoren verwenden?
Eine praktische Faustregel:
Verwende einen faulen Quantor, wenn du bis zum ersten Vorkommen eines Trennzeichens matchen willst, und einen gierigen, wenn du alles bis zum letzten willst.
Häufige Situationen, in denen faul die richtige Wahl ist:
- Einzelnen HTML/XML-Tag extrahieren:
/<.*?>/. - Inhalt eines einzelnen Anführungszeichen- oder Klammerpaars erfassen:
/".*?"/,/\(.*?\)/. - Text bis zum nächsten Trennzeichen greifen, ohne in den folgenden Datensatz zu überschießen.
Zwei wichtige Vorbehalte:
- Ein Trennzeichen ist oft klarer als Faulheit. Statt
/".*?"/kann man/"[^"]*"/mit einer negierten Zeichenklasse schreiben. Damit entfällt Backtracking vollständig, und das Muster ist in der Regel schneller und vorhersehbarer. - Faul braucht etwas, worauf es stoppen kann. Wie das Beispiel mit
AB.*?gezeigt hat, kollabiert ein fauler Quantor am Ende eines Musters (ohne etwas, das ihn vorwärtsdrängt) auf sein Minimum und matcht fast nichts. Kombiniere ihn stets mit einem nachfolgenden Literal, Anker oder einer Einfanggruppe.
Zusammenfassung
- Quantoren sind standardmäßig gierig — sie nehmen das Maximum und machen dann Backtracking, damit der Rest des Musters passt.
?anhängen macht einen Quantor faul — er nimmt das Minimum und weitet sich nur aus, wenn er dazu gezwungen wird.- Ein fauler Quantor ohne nachfolgendes Element matcht so wenig wie rechtlich möglich (oft nichts), daher immer ein Trennzeichen oder einen Anker angeben, auf dem er stoppen kann.
- Die vollständige faule Familie umfasst
*?,+?,??und{n,m}?. - Greife zu Faul, wenn du „bis zum ersten" Trennzeichen willst; andernfalls ist eine negierte Zeichenklasse oft die sauberere und schnellere Wahl.