Ich versuche, einen String mit Regex in zwei Teile aufzuteilen. Die Zeichenfolge ist wie folgt formatiert:
text to extract<number>
Ich habe verwendet (.*?)<
und <(.*?)>
welche funktionieren gut, aber nachdem ich ein wenig in Regex gelesen habe, habe ich mich gerade gefragt, warum ich das ?
in den Ausdrücken brauche . Ich habe es erst so gemacht, nachdem ich sie über diese Seite gefunden habe, also bin ich mir nicht ganz sicher, was der Unterschied ist.
Antworten:
Es ist der Unterschied zwischen gierigen und nicht gierigen Quantifizierern.
Betrachten Sie die Eingabe
101000000000100
.Verwenden
1.*1
,*
ist gierig - es wird bis zum Ende übereinstimmen und dann zurückverfolgen, bis es übereinstimmen kann1
, so dass Sie mit1010000000001
..*?
ist nicht gierig.*
wird mit nichts übereinstimmen, wird dann aber versuchen, zusätzliche Zeichen zuzuordnen, bis sie übereinstimmen1
, und schließlich übereinstimmen101
.Alle quantifiers haben einen nicht-gierigen Modus:
.*?
,.+?
,.{2,6}?
, und sogar.??
.In Ihrem Fall könnte ein ähnliches Muster sein
<([^>]*)>
- es entspricht nichts anderem als einem Größer-als-Zeichen (genau genommen entspricht es null oder mehr Zeichen außer>
dazwischen<
und>
).Siehe Quantifier Cheat Sheet .
quelle
?
vom Nicht-Gierigen unterscheidet??
?"abc"
der reguläre Ausdruck/\w\w?\w/
mit der vollständigen Zeichenfolge übereinstimmen"abc"
- da dies?
gierig ist./\w\w??\w/
ist faul - es wird nur passen"ab"
. Es wird nur zurückverfolgt und abgeglichen,"abc"
wenn es später fehlschlägt.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
undA.*?Z
.Angesichts der folgenden Eingabe:
Die Muster ergeben die folgenden Übereinstimmungen:
A.*Z
ergibt 1 Übereinstimmung:AiiZuuuuAoooZ
( siehe auf rubular.com )A.*?Z
ergibt 2 Übereinstimmungen:AiiZ
undAoooZ
( siehe auf rubular.com )Konzentrieren wir uns zunächst auf das, was
A.*Z
tut. Wenn es mit dem ersten übereinstimmt , versuchtA
der.*
, der gierig ist, zuerst so viele.
wie möglich zu finden.Da das
Z
nicht übereinstimmt, fährt der Motor zurück und.*
muss dann eins weniger übereinstimmen.
:Dies passiert noch einige Male, bis wir schließlich dazu kommen:
Jetzt
Z
kann übereinstimmen, so dass das Gesamtmuster übereinstimmt: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:
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 dasA.*?Z
Muster für die obige Eingabe ( wie auf ideone.com zu sehen ).[^Z]
wird als negierte Zeichenklasse bezeichnet : Sie passt zu allem anderenZ
.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.
Dies sind die Übereinstimmungen für die obige Eingabe:
A[^Z]*ZZ
ergibt 1 Übereinstimmung:AuuZZ
( wie auf ideone.com zu sehen )A.*?ZZ
ergibt 1 Übereinstimmung:AiiZooAuuZZ
( wie auf ideone.com zu sehen )A.*ZZ
ergibt 1 Übereinstimmung:AiiZooAuuZZeeeZZ
( wie auf ideone.com zu sehen )Hier ist eine visuelle Darstellung dessen, was sie übereinstimmten:
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
quelle
Angenommen, Sie haben:
<(.*)>
würde passen,a></a
wo wie<(.*?)>
passen würdea
. Letzterer stoppt nach dem ersten Spiel von>
. Es wird nach einer oder 0 Übereinstimmungen.*
gefolgt vom nächsten Ausdruck gesucht.Der erste Ausdruck
<(.*)>
hört nicht auf, wenn er mit dem ersten übereinstimmt>
. Es wird bis zum letzten Spiel von fortgesetzt>
.quelle