507 Stimmen

Wie kann ich eine Regex schreiben, die nicht gierig passt?

Ich brauche Hilfe bei der Suche nach regulären Ausdrücken mit der Option non-greedy.

Das Übereinstimmungsmuster ist:

<img\s.*>

Der zu übereinstimmende 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 aus <img bis zuletzt > . Ich brauche es, um mit dem ersten begegnet passen > nach der anfänglichen <img In diesem Fall müsste ich also zwei Streichhölzer besorgen, statt nur eines zu bekommen.

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

709voto

Pavan Manjunath Punkte 26281

Die Nicht-Gierigen ? funktioniert einwandfrei. Es ist nur so, dass Sie Folgendes auswählen müssen Punkt passt zu allen Option in den Regex-Engines ( regexpal , der von Ihnen verwendete Motor, verfügt ebenfalls über diese Option), mit der Sie testen. Der Grund dafür ist, dass Regex-Engines im Allgemeinen keine Zeilenumbrüche abgleichen, wenn Sie . . Sie müssen ihnen ausdrücklich sagen, dass Sie auch Zeilenumbrüche abgleichen wollen mit .

Zum Beispiel,

<img\s.*?>

funktioniert einwandfrei!

Prüfen Sie die Ergebnisse hier .

Lesen Sie auch über 如何して Punkt verhält sich in verschiedenen Regex-Varianten.

148voto

Ilya Punkte 1774

Le ? Operand macht die Übereinstimmung nicht gierig. z.B. .* ist gierig, während .*? ist es nicht. Sie können also etwas verwenden wie <img.*?> um den gesamten Tag abzugleichen. Oder <img[^>]*> .

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

34voto

tripleee Punkte 155951

Die anderen Antworten hier setzen voraus, dass Sie eine Regex-Engine haben, die Non-Greedy-Matching unterstützt. Dies ist eine Erweiterung, die in Perl 5 eingeführt und in andere moderne Sprachen übernommen wurde; sie ist aber keineswegs allgegenwärtig.

Viele ältere oder konservativere Sprachen und Editoren unterstützen nur traditionelle reguläre Ausdrücke, die keinen Mechanismus zur Kontrolle der Gierigkeit des Wiederholungsoperators haben * - wird immer die längste mögliche Zeichenkette gefunden.

Der Trick besteht also darin, das zu begrenzen, was er überhaupt abgleichen darf. Anstelle von .* Sie scheinen zu suchen

[^>]*

die immer noch mit so vielen der etwas wie möglich; aber die etwas ist nicht nur . "jedes Zeichen", sondern "jedes Zeichen, das nicht > ".

Je nach Anwendung kann es sinnvoll sein, eine Option zu aktivieren, die "beliebige Zeichen" einschließlich Zeilenumbrüchen zulässt.

Selbst wenn Ihre Engine für reguläre Ausdrücke eine nicht-gierige Suche unterstützt, ist es besser, genau zu sagen, was Sie eigentlich meinen. Wenn dies です was Sie meinen, sollten Sie dies wahrscheinlich sagen, anstatt sich auf eine nicht gierige Übereinstimmung zu verlassen, um (hoffentlich, wahrscheinlich) zu tun, was ich meine.

Ein regulärer Ausdruck mit einem nachgestellten Kontext nach dem Platzhalter wie z. B. .*?><br/> überspringt jede verschachtelte > bis es den hinteren Kontext findet (hier, ><br/> ), auch wenn dies die Überwindung mehrerer > Instanzen und Zeilenumbrüche, wenn Sie es zulassen, wobei [^>]*><br/> (oder sogar [^\n>]*><br/> wenn Sie den Zeilenumbruch explizit verbieten müssen) kann und will das natürlich nicht tun.

Natürlich ist das immer noch nicht das, was Sie wollen, wenn Sie sich mit <img title="quoted string with > in it" src="other attributes"> and perhaps <img title="nested tags"> aber an diesem Punkt sollten Sie es endgültig aufgeben, reguläre Ausdrücke dafür zu verwenden, wie wir es Ihnen alle von Anfang an gesagt haben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X