Regulärer Ausdruck, um beim ersten Spiel anzuhalten

531

Mein Regex-Muster sieht ungefähr so ​​aus

<xxxx location="file path/level1/level2" xxxx some="xxx">

Ich interessiere mich nur für den Teil in Anführungszeichen, die dem Standort zugeordnet sind. Sollte es ohne den gierigen Schalter nicht so einfach sein wie unten?

/.*location="(.*)".*/

Scheint nicht zu funktionieren.

publicRavi
quelle
Was ist deine Quelle, ist es HTML oder XML oder so?
Oskar Kjellin
20
Warum ist das ein Community-Wiki? Das ist eine echte Frage. Jetzt ist es zu spät.
Ahmad Mageed
1
In welcher Sprache schreibst du? Bitte verwenden Sie keinen regulären Ausdruck für XML. Es gibt so viele bessere Möglichkeiten, XML zu analysieren
Oskar Kjellin
3
Nicht, wenn Sie nur nach einfachen Attributen suchen möchten. Regex ist angemessen und schneller.
Codenheim
Ich würde sagen, wenn Sie zum Beispiel Code c # verwenden, ist es viel besser, dafür linq zu verwenden. Ich bezweifle, dass es besser ist, Regex zu machen, wenn Sie einen guten Parser haben
Oskar Kjellin

Antworten:

1096

Sie müssen Ihren regulären Ausdruck nicht gierig machen, da standardmäßig "(.*)"alle übereinstimmen "file path/level1/level2" xxx some="xxx".

Stattdessen können Sie Ihren Punktstern nicht gierig machen, wodurch er so wenig Zeichen wie möglich entspricht:

/location="(.*?)"/

Hinzufügen eines ?auf einem Quantor ( ?, *oder +) macht es nicht gierig.

Daniel Vandersluis
quelle
32
FWIW, incase Ihr mit VIM, diese Regex Bedürfnisse ein wenig anders sein: statt .*?es ist .\{-}für eine nicht gierige Spiel.
SooDesuNe
44
Danke Daniel. "Das Hinzufügen eines? An einem Quantifizierer (?, * Oder +) macht ihn nicht gierig." ist ein hilfreicher Tipp für mich.
PhatHV
10
Das ? beschreibt meine Verwirrung beim Versuch, dies herauszufinden. Wie angemessen.
Robbie Smith
1
Ich glaube, Sie können "faul" statt "nicht gierig" sagen
Manticore
50

location="(.*)"wird von "nach location=bis" nachher übereinstimmen some="xxx, es sei denn, Sie machen es nicht gierig. So müssen Sie entweder .*?(dh es nicht gierige) oder besser ersetzen .*mit [^"]*.

sepp2k
quelle
3
[^ "] * ist wahrscheinlich auch schneller mit den meisten Regex-Engines, da das Muster nicht nach dem aktuellen Muster
Jean Vincent
1
@ Kip: Sie haben wahrscheinlich Recht, aber die .*?Notation ist allgemeiner als[^"]*
Bondax
Wie wäre es, wenn ich das Trennzeichen mit [^ "] *
Fröhlich
überhaupt nicht, wenn Sie nicht wissen, was ^ und [] hier bedeuten. Die meisten Leute werden verstehen. *
Vincent Gerris
31

Wie wäre es mit

.*location="([^"]*)".*

Dies vermeidet die unbegrenzte Suche mit. * Und stimmt genau mit dem ersten Zitat überein.

Benutzer193690
quelle
Aufgrund von Unstimmigkeiten in grep sollte das Obige das bevorzugte Muster sein, wenn die Portabilität ein Problem darstellt.
Josh Habdas
22

Verwenden Sie nicht gieriges Matching, wenn Ihr Motor dies unterstützt. Ergänzen Sie die ? innerhalb der Aufnahme.

/location="(.*?)"/
Codenheim
quelle
11

Die Verwendung von Lazy-Quantifizierern ?ohne globales Flag ist die Antwort.

Z.B,

Geben Sie hier die Bildbeschreibung ein

Wenn Sie dann ein globales Flag hätten /g, hätte es mit allen Übereinstimmungen mit der niedrigsten Länge wie unten übereinstimmen können. Geben Sie hier die Bildbeschreibung ein

Uddhav Gautam
quelle
1

Da Sie ein quantifiziertes Untermuster verwenden und wie in Perl Doc beschrieben ,

Standardmäßig ist ein quantifiziertes Untermuster " gierig ", dh es stimmt so oft wie möglich überein (bei einem bestimmten Startort), während der Rest des Musters weiterhin übereinstimmt. Wenn Sie möchten, dass es so oft wie möglich übereinstimmt , folgen Sie dem Quantifizierer mit einem "?" . Beachten Sie, dass sich die Bedeutungen nicht ändern, nur die "Gier":

*?        //Match 0 or more times, not greedily (minimum matches)
+?        //Match 1 or more times, not greedily

Um Ihrem quantifizierten Muster eine minimale Übereinstimmung zu ermöglichen, gehen Sie folgendermaßen vor ?:

/location="(.*?)"/
Mohammad Kanan
quelle
1

Hier ist ein anderer Weg.

Hier ist der, den du willst. Das ist faul[\s\S]*?

Der erste Punkt: [\s\S]*?(?:location="[^"]*")[\s\S]* Ersetzen durch:$1

Erklärung : https://regex101.com/r/ZcqcUm/2


Der Vollständigkeit halber erhält dies den letzten. Das ist gierig[\s\S]*

Der letzte Punkt:[\s\S]*(?:location="([^"]*)")[\s\S]* Ersetzen durch:$1

Erklärung : https://regex101.com/r/LXSPDp/3


Es gibt nur einen Unterschied zwischen diesen beiden regulären Ausdrücken und das ist der ?

Stephen Sherry
quelle