it-swarm.com.de

Wie kann ich einen Regex schreiben, der nicht gierig ist?

Ich brauche Hilfe zum Abgleich von regulären Ausdrücken mit nicht-gieriger Option.

Das Übereinstimmungsmuster ist:

<img\s.*>

Der passende Text lautet:

<html>
<img src="test">
abc
<img
  src="a" src='a' a=b>
</html>

Ich teste auf http://regexpal.com

Dieser Ausdruck entspricht dem gesamten Text von <img bis zum letzten >. Ich brauche es, um mit dem ersten angetroffenen > nach dem anfänglichen <img übereinzustimmen, daher müsste ich hier zwei Übereinstimmungen anstelle des ermittelten finden.

Ich habe alle Kombinationen von nicht-gierig ? ausprobiert, ohne Erfolg.

254
Pointer Null

Der nicht-gierige ? funktioniert einwandfrei. Sie müssen lediglich auswählen, dass dot für alle Optionen der Option in den Regex-Engines (regexpal, die Engine, die Sie verwendet haben, auch diese Option hat), die Sie testen. Dies liegt daran, dass Regex-Engines im Allgemeinen nicht mit Zeilenumbrüchen übereinstimmen, wenn Sie . verwenden. Sie müssen ihnen explizit mitteilen, dass Sie auch Zeilenumbrüche mit . abgleichen möchten.

Zum Beispiel,

<img\s.*?>

funktioniert gut!

Überprüfen Sie die Ergebnisse hier .

Lesen Sie auch über wie sich dot verhält in verschiedenen Regex-Varianten.

368
Pavan Manjunath

Der ?-Operand macht die Übereinstimmung nicht gierig. Z.B. .* ist gierig, .*? nicht. Sie können also etwas wie <img.*?> verwenden, um das gesamte Tag abzugleichen. Oder <img[^>]*>.

Denken Sie jedoch daran, dass der gesamte HTML-Satz nicht mit regulären Ausdrücken analysiert werden kann.

60
Ilya

Check Stack Overflow question Was bedeutet faul und gierig im Zusammenhang mit regulären Ausdrücken? auch.

Gierig bedeutet, dass die längste mögliche Zeichenfolge übereinstimmt.

Lazy bedeutet Übereinstimmung mit der kürzest möglichen Zeichenfolge.

Zum Beispiel entspricht das gierige h. + L der 'Hölle' in 'hallo', aber das faule h. +? L stimmt mit 'hel' überein.

1
Rahul

Die anderen Antworten hier setzen voraus, dass Sie über einen Regex-Angine verfügen, der nicht gieriges Matching unterstützt. Dies ist eine Erweiterung, die in Perl 5 eingeführt wurde und weitgehend in andere moderne Sprachen übernommen wurde. aber es ist keineswegs allgegenwärtig. Viele ältere Sprachen und Editoren unterstützen nur herkömmliche reguläre Ausdrücke, die keinen Mechanismus zur Steuerung der Gierigkeit des Wiederholungsoperators * haben - er entspricht immer der längsten möglichen Zeichenfolge.

Der Trick besteht dann darin, das zu begrenzen, was zuerst passen darf. Anstelle von .* scheinen Sie zu suchen

[^>]*

was noch so viele von etwas wie möglich zusammenbringt; aber das etwas ist nicht nur . "irgendein Zeichen", sondern "beliebiges Zeichen", das nicht > ist.

Abhängig von Ihrer Anwendung möchten Sie möglicherweise eine Option aktivieren, die zulässt, dass "beliebige Zeichen" Zeilenumbrüche enthalten.

Selbst wenn Ihr Regex-Modul nicht gierige Übereinstimmungen unterstützt, ist es besser zu formulieren, was Sie eigentlich meinen. Wenn dies ist was Sie meinen, sollten Sie dies wahrscheinlich sagen, anstatt sich auf nicht-gierige Übereinstimmung zu verlassen (hoffentlich wahrscheinlich), was ich meine.

Natürlich ist dies immer noch nicht das, was Sie wollen, wenn Sie mit <img title="quoted string with > in it" src="other attributes"> and perhaps <img title="nested tags"> fertig werden müssen, aber an diesem Punkt sollten Sie schließlich die Verwendung von Regex aufgeben, wie wir es Ihnen zuvor alles gesagt hatten.

0
tripleee