Da Google diese Frage SO oben auf die Ergebnisse für die tempered greedy token
zurück, fühle ich mich verpflichtet, eine umfassende Antwort zu geben.
Was ist ein ausgehärtetes Greedy Token?
Die rexegg.com tempered greedy token Referenz ist recht prägnant:
In (?:(?!{END}).)*
, die *
quantifier auf einen Punkt trifft, aber es ist jetzt ein temperiert Punkt. Der negative Lookahead (?!{END})
behauptet, dass das, was der aktuellen Position folgt, nicht die Zeichenfolge {END}
ist. Daher kann der Punkt niemals mit der öffnenden Klammer von {END}
übereinstimmen, was garantiert, dass wir nicht über den {END}
Begrenzer springen werden.
, dass es: a temperierte gierig Token ist eine Art einer negierte Zeichenklasse für ein Zeichen Sequenz (vgl negated character class für ein einzelnes Zeichen).
HINWEIS: Der Unterschied zwischen einem temperierten gierigen Token und einer negierte Zeichenklasse ist, dass erstere nicht wirklich den Text übereinstimmt anders als die Sequenz selbst, sondern ein einzelne Zeichen, die nicht startet diese Sequenz . I.e.(?:(?!abc|xyz).)+
nicht def
in defabc
, passen aber def
undbc
, überein, da a
die verbotene abc
Sequenz beginnt, und bc
nicht.
Es besteht aus:
(?:...)*
- eine quantifizierte Nicht-Erfassung Gruppe (es eine Erfassungsgruppe sein kann, aber es macht keinen Sinn, jeden einzelnen Charakter zu erfassen) (a *
kann +
sein, es hängt ob ein leerer String Spiel erwartet wird)
(?!...)
- eine negative lookahead, die tatsächlich eine Beschränkung des Wertes rechts von der aktuellen Position
.
erlegt - (oder einem (in der Regel einzeln) Zeichen) ein verzehr Muster.
können wir jedoch immer weiter das Token Temperament von Abwechslungen im negativen Look-Ahead (zB (?!{(?:END|START|MID)})
) oder durch Ersetzen der alle Anpassungs Punkt mit einem negierten Zeichenklasse (zB (?:(?!START|END|MID)[^<>])
wenn sie versuchen, Text innerhalb von Tags nur passend).
aufwendigste Teil Platzierung
Hinweis gibt es keine Erwähnung eine Konstruktion ist, wo ein verzehrender Teil (der Punkt in den ursprünglichen temperiert gierigen Token) vor der Look-Ahead platziert wird. Avinashs Antwort erklärt diesen Teil klar: (.(?!</table>))*
passt zuerst auf ein beliebiges Zeichen (aber eine Zeilenschaltung ohne einen Modifikator DOTALL) und prüft dann, ob es nicht mit </table>
übereinstimmt, was dazu führt, dass e
in <table>table</table>
nicht übereinstimmt. Der verbrauchende Teil (.
) MUSS nach dem Temperieren Lookahead platziert werden.
Wann temperierte gierige Token zu verwenden?
Rexegg.com gibt eine Idee:
- Wenn wir einen Textblock zwischen Trennzeichen 1 und 2 Trennzeichen ohne Substring 3 in-between (zB
{START}(?:(?!{(?:MID|RESTART)}).)*?{END}
- übereinstimmen soll Wenn wir vergleichen wollen ein Text ein bestimmtes Muster innerhalb ohne überzulaufen nachfolgende Blöcke enthält (zB statt faul Punktanpassung, wie in
<table>.*?chair.*?</table>
, würden wir so etwas wie <table>(?:(?!chair|</?table>).)*chair(?:(?!<table>).)*</table>
verwenden).
- Wenn wir die kürzesten Fenster möglich zwischen 2 str übereinstimmen sollen iings. Lazy Matching wird nicht helfen, wenn Sie
abc 2 xyz
von abc 1 abc 2 xyz
erhalten müssen (siehe abc.*?xyz
und abc(?:(?!abc).)*?xyz
).
Leistungsproblem
Ausgeglichenes gierig Token ist ressourcenaufwändig als Look-Ahead-Check nach jedem Zeichen mit dem raubend Muster abgestimmt durchgeführt wird. Unrolling the loop technique kann die temperierte Greedy-Token-Leistung erheblich steigern.
Sag mal, wollen wirabc 2 xyz
in abc 1 abc 2 xyz 3 xyz entsprechen.Statt jedes Zeichen zwischen abc
und xyz
mit abc(?:(?!abc|xyz).)*xyz
zu prüfen, können wir alle Zeichen überspringen, die nicht a
oder x
mit [^ax]*
sind, und dann alle a
übereinstimmen, die nicht mit bc
(mit a(?!bc)
) und alle x
gefolgt werden, die nicht mit yz
befolgt werden (mit x(?!yz)
): abc[^ax]*(?:a(?!bc)[^ax]*|x(?!yz)[^ax]*)*xyz
.
Nebenbei bemerkt, dass diese "temperierte" Art besonders ineffizient ist. –
@sln Nein, ich habe es nicht erfunden. Tatsächlich verweist der letzte Satz meiner Post, wo der Begriff herkam ... – jrahhali
Dann .. _he_ hat es erfunden. In der Tat, das ist kein Standard-Jargon in Regex Land. Und wenn ich eine Umfrage machen würde, wette ich, dass 99% der Regex-Gurus darüber lachen würden. – sln