Regex: dopasowanie do pierwszego wystąpienia postaci

356

Szukam wzoru, który pasuje do wszystkiego do do pierwszego wystąpienia określonej postaci, powiedz „;” - średnik .

Ja to napisałem:

/^(.*);/

Ale tak naprawdę pasuje do wszystkiego (w tym średnika) aż do ostatniego wystąpienia średnika.

Leon Fiedotow
źródło
65
/^(.*?);/powinien również działać (nazywa się to nie chciwym ), ale podane odpowiedzi [^;]*są lepsze.
Pascal
jak wybrałbyś wszystko po średniku, a nie sam średnik.
Muhammad Umer,
widzisz, jak to działa, \w+(?!([^]+;)|;)ale nie dlatego? .+(?!([^]+;)|;)
Muhammad Umer,
1
Pascal, powinieneś to napisać jako odpowiedź!
Sean Kendle,
@Pascal To jest odpowiednie jako odpowiedź! Dzięki!
neverMind9

Odpowiedzi:

503

Potrzebujesz

/[^;]*/

[^;]Jest klasa znaków , która pasuje do wszystkiego oprócz średnika.

Aby zacytować stronę perlre:

Możesz określić klasę znaków, umieszczając listę znaków w [], która będzie pasować do dowolnego znaku z listy. Jeśli pierwszym znakiem po „[” jest „^”, klasa pasuje do dowolnego znaku spoza listy.

Powinno to działać w większości dialektów wyrażeń regularnych.

Śleske
źródło
Świetną częścią tego rozwiązania jest to, że pasuje również do końca linii, np. W moim przypadku miałem foo=bar;baz=bax;bab=bafi pasowało bab=bafnawet tam, gdzie nie ma ;dokładnie tego, czego potrzebuję. Nie jestem pewien, dlaczego to działa, jeśli spec mówi, że pasuje do wszystkiego oprócz symbolu docelowego ...
skryvets
303

By;

/^(.*?);/

praca?

?Jest lazy operatora, że wyrażenie regularne chwyta tak mało jak to możliwe, przed dopasowaniu ;.

RJFalconer
źródło
4
ya, ale po rozszerzeniu wodorowęglanu do Tima Toady'ego uważam, że wygrane klasy postaci wygrywają, ponieważ leniwy kwantyfikator obejmuje wycofywanie. W każdym razie +1.
Amarghosh
3
Warto przeczytać na temat wykonania: blog.stevenlevithan.com/archives/greedy-lazy-performance
Glenn Slaven
38

/^[^;]*/

[^;] Mówi, że pasuje do wszystkiego oprócz średnika. Nawiasy kwadratowe są operatorem dopasowywania zestawu, w zasadzie dopasowują dowolny znak w tym zestawie znaków, ^na początku powoduje odwrotne dopasowanie, więc dopasuj wszystko, co nie jest w tym zestawie.

Glenn Slaven
źródło
3
Pamiętaj, że pierwsze ^ w tej odpowiedzi nadaje regexowi zupełnie inne znaczenie: sprawia, że ​​wyrażenie regularne szuka tylko dopasowań zaczynających się od początku łańcucha. W takim przypadku byłoby to efektywne, gdybyś nie uruchomił wyrażenia regularnego tylko raz. Jeśli chcesz wyszukać wiele dopasowań w jednym ciągu, pierwsze ^ musiałoby odejść.
Dan Breslau
4
Powiedział, że chce dopasować wszystko do pierwszego wystąpienia średnika, więc założyłem, że miał na myśli od początku łańcucha.
Glenn Slaven
15

Próbować /[^;]*/

Google regex character classesdla szczegółów.

Dan Breslau
źródło
8

przykładowy tekst:

"this is a test sentence; to prove this regex; that is g;iven below"

Jeśli na przykład mamy powyższy przykładowy tekst, regex /(.*?\;)/da ci wszystko do pierwszego wystąpienia średnika ( ;), w tym średnika:"this is a test sentence;"

poncius
źródło
3
nie trzeba uciekać od ;znaku, ponieważ nie jest to wyrażenie specjalne wyrażenia regularnego. Grupowanie również ()nie jest wymagane. Możesz iść z/.*?;/
Aliaksei Kliuchnikau
1
tak, masz całkowitą rację. ucieczka była bardziej jak „lepiej bezpiecznie niż przepraszać”
poncius
2
Oto odpowiedź, której szukałem. Więc? sprawia, że ​​mecz kończy się za pierwszym razem? Jak nazywa się ta ... (nazwijmy to) właściwość wyrażenia regularnego?
Parziphal
1
@Parziphal ?postać sprawia, że ​​mecz jest leniwy (dopasowuje tyle razy, ile to możliwe). Pomyśl o wyrażeniach pasujących do wyrażenia regularnego aż do pierwszego średnika, a potem nie pójdzie dalej, ponieważ się poddaje (leniwy;))
derekantrican
5

nie jest to rozwiązanie wyrażenia regularnego, ale coś wystarczająco prostego do opisu problemu. Po prostu podziel swój ciąg i zdobądź pierwszy przedmiot z tablicy.

$str = "match everything until first ; blah ; blah end ";
$s = explode(";",$str,2);
print $s[0];

wynik

$ php test.php
match everything until first
ghostdog74
źródło
5

Było to dla mnie bardzo pomocne, gdy próbowałem wymyślić, jak dopasować wszystkie znaki w tagu xml, w tym atrybuty. Wystąpił problem „dopasowuje wszystko do końca” z:

/<simpleChoice.*>/

ale udało się rozwiązać problem z:

/<simpleChoice[^>]*>/

po przeczytaniu tego postu. Dziękuje wszystkim.

Yardboy
źródło
1
Przekonałem się, że o wiele bardziej efektywne jest parsowanie (każdy język lub framework ma do tego swoje własne klasy) html / xml ze względu na format maszynowy, wyrażenia regularne są dla języka naturalnego.
Leon Fedotov,
1
Miły. Użyłem tego, aby naprawić dokumenty XML z błędami składniowymi w <!DOCTYPE>znaczniku. Ponieważ parser nie był w stanie sobie z tym poradzić.
Martin Schneider,
5

Spowoduje to dopasowanie do pierwszego wystąpienia tylko w każdym ciągu i zignoruje kolejne wystąpienia.

/^([^;]*);*/
mchid
źródło
3

"/^([^\/]*)\/$/" pracował dla mnie, aby uzyskać tylko najlepsze „foldery” z tablicy takiej jak:

a/   <- this
a/b/
c/   <- this
c/d/
/d/e/
f/   <- this
sPooKee
źródło
2

Naprawdę mi przykro, że nikt nie dał prawidłowej odpowiedzi ....

W wyrażeniach regularnych? sprawia, że ​​nie jest chciwy. Domyślnie regex będzie pasował jak najwięcej (zachłanny)

Po prostu dodać? i nie będzie chciwy i będzie pasował tak mało, jak to możliwe!

Powodzenia, mam nadzieję, że to pomaga.

L1amm
źródło
3
Zależy to w dużej mierze od faktycznej implementacji wyrażenia regularnego i nie każda implementacja ma tryb nie chciwy.
karatedog
0

znalazłem to

/^[^,]*,/

działa dobrze.

„,” będący tutaj „ogranicznikiem”.

BookerVII
źródło