Wyrażenie regularne zatrzymujące się przy pierwszym dopasowaniu


528

Mój wzór wyrażenia regularnego wygląda mniej więcej tak

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

Interesuje mnie tylko ta część cytatów przypisanych do lokalizacji. Czy nie powinno być tak łatwe jak poniżej bez chciwego przełącznika?

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

Nie wydaje się działać.


Jakie jest twoje źródło, czy to HTML, xml czy coś?
Oskar Kjellin

20
Dlaczego jest to wiki społeczności? To prawdziwe pytanie. Teraz już za późno.
Ahmad Mageed

1
W jakim języku piszesz? Proszę nie używać wyrażenia regularnego dla XML. Jest wiele lepszych sposobów na parsowanie XML
Oskar Kjellin

3
Nie, jeśli wszystko, czego chcesz, to skanowanie w poszukiwaniu prostych atrybutów. Regex jest odpowiedni i szybszy.
codenheim

Powiedziałbym, że jeśli na przykład użyjesz kodu c #, o wiele lepiej jest użyć do tego linq. Wątpię, czy lepiej będzie regex, jeśli masz dobry parser
Oskar Kjellin

Odpowiedzi:


1092

Musisz sprawić, by wyrażenie regularne nie było zachłanne, ponieważ domyślnie "(.*)"będzie pasowało do wszystkich "file path/level1/level2" xxx some="xxx".

Zamiast tego możesz sprawić, by twoja gwiazda kropka nie była chciwa, co sprawi, że będzie pasować jak najmniej znaków:

/location="(.*?)"/

Dodanie ?na kwantyfikatorem ( ?, *lub +) sprawia, że nie chciwi.


32
FWIW, okrywać swoich potrzeb za pomocą vim regex to być trochę inaczej: zamiast .*?to .\{-}dla nie-chciwy meczu.
SooDesuNe

44
Dzięki Daniel. „Dodanie? Do kwantyfikatora (?, * Lub +) powoduje, że nie jest on chciwy.” jest dla mnie pomocna wskazówka.
PhatHV,

10
The? opisuje moje zamieszanie przy próbie zrozumienia tego. Jak odpowiedni.
Robbie Smith,

1
Wierzę, że można powiedzieć „leniwy” zamiast „nie chciwy”
Manticore,

50

location="(.*)"dopasuje od „po location=do” po, some="xxxchyba że sprawisz, że nie będzie chciwy. Więc albo musisz .*?(tj. Sprawić, że będzie niechciany), albo lepiej zastąp .*go [^"]*.


3
[^ "] * jest również prawdopodobnie szybszy w przypadku większości silników wyrażeń regularnych, ponieważ nie musi wyszukiwać wzorca po bieżącym wzorcu.
Jean Vincent

1
@Kip: Prawdopodobnie masz rację, ale .*?notacja jest bardziej ogólna niż[^"]*
Bondax

co powiesz na to, czy chcę dołączyć znak ogranicznika za pomocą [^ "] *
Frohlich,

wcale nie, jeśli nie wiesz, co oznaczają ^ i []. Większość ludzi zrozumie. *
Vincent Gerris,

31

Co powiesz na

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

Pozwala to uniknąć nieograniczonego wyszukiwania za pomocą. * I pasuje dokładnie do pierwszego cytatu.


Ze względu na rozbieżności w grep, powyższy powinien być preferowanym wzorcem, jeśli chodzi o przenośność.
Josh Habdas,

22

Użyj niepochodnego dopasowania, jeśli Twój silnik to obsługuje. Dodaj ? wewnątrz schwytania.

/location="(.*?)"/

11

Odpowiedzią jest użycie leniwych kwantyfikatorów ?bez flagi globalnej.

Na przykład,

wprowadź opis zdjęcia tutaj

Gdybyś miał /gwtedy flagę globalną , pasowałby do wszystkich dopasowań o najniższej długości, jak poniżej. wprowadź opis zdjęcia tutaj


1

Ponieważ używasz ilościowego subpattern i jak opisano w Perl Doc ,

Domyślnie kwantyfikowany wzorzec jest „ zachłanny ”, to znaczy będzie pasował tyle razy, ile to możliwe (biorąc pod uwagę konkretną lokalizację początkową), jednocześnie umożliwiając dopasowanie pozostałej części wzorca. Jeśli chcesz, aby odpowiadała minimalnej możliwej liczbie razy , podążaj za kwantyfikatorem za pomocą „?” . Zauważ, że znaczenia się nie zmieniają, tylko „chciwość”:

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

Dlatego, aby pozwolić twojemu wzorcu ilościowemu na dopasowanie minimalne, wykonaj następujące czynności ?:

/location="(.*?)"/

1

Oto inny sposób.

Oto ten, którego chcesz. To jest leniwe[\s\S]*?

Pierwszy element: [\s\S]*?(?:location="[^"]*")[\s\S]* Zamień na:$1

Wyjaśnienie : https://regex101.com/r/ZcqcUm/2


Dla kompletności otrzymuje się ostatni. To jest chciwe[\s\S]*

Ostatni element:[\s\S]*(?:location="([^"]*)")[\s\S]* Zamień na:$1

Wyjaśnienie : https://regex101.com/r/LXSPDp/3


Jest tylko jedna różnica między tymi dwoma wyrażeniami regularnymi i to jest ?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.