Regex lookahead, lookbehind i atomic groups

314

Znalazłem te rzeczy w moim wyrażeniu regularnym, ale nie mam pojęcia, do czego mogę ich użyć. Czy ktoś ma przykłady, więc mogę spróbować zrozumieć, jak działają?

(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind

(?>) - atomic group
Spidfire
źródło
18
Dlaczego strona regex nie ma takiej prostej tabeli? Zamiast tego mają tylko bloki tekstu wyjaśniające. regular-expressions.info/lookaround.html
Whitecat
3
@Whitecat Wypróbuj: regex101.com regexr.com
Andrew

Odpowiedzi:

851

Przykłady

Biorąc pod uwagę ciąg foobarbarfoo:

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

Możesz je również łączyć:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

Definicje

Patrz w przyszłość pozytywnie (?=)

Znajdź wyrażenie A, po którym następuje wyrażenie B:

A(?=B)

Patrz w przyszłość negatywnie (?!)

Znajdź wyrażenie A, w którym nie występuje wyrażenie B:

A(?!B)

Spójrz za siebie (?<=)

Znajdź wyrażenie A, w którym wyrażenie B poprzedza:

(?<=B)A

Spójrz za negatywne (?<!)

Znajdź wyrażenie A, w którym wyrażenie B nie poprzedza:

(?<!B)A

Grupy atomowe (?>)

Grupa atomowa wychodzi z grupy i wyrzuca alternatywne wzorce po pierwszym dopasowanym wzorcu w grupie (cofanie jest wyłączone).

  • (?>foo|foot)szastosowane do footsdopasuje swoją pierwszą alternatywę foo, a następnie zakończy się niepowodzeniem, ponieważ snie następuje natychmiast, i zatrzyma się, gdy cofanie będzie wyłączone

Grupa nieatomowa pozwoli na powrót; jeśli kolejne dopasowanie z wyprzedzeniem nie powiedzie się, nastąpi powrót i użycie alternatywnych wzorców do momentu znalezienia dopasowania dla całego wyrażenia lub wyczerpania wszystkich możliwości.

  • (foo|foot)sstosowane do foots:

    1. dopasuj pierwszą alternatywę foo, a następnie zawiod, ponieważ snie następuje natychmiast foots, i cofnij się do drugiej alternatywy;
    2. dopasuj drugą alternatywę foot , a następnie odnieś sukces, jak tylko snastąpi foots, i zatrzymaj się.

Niektóre zasoby

Testerzy online

podniebna
źródło
1
Co rozumiesz przez część „znajduje drugi takt”? W wyrażeniu / ciągu znajduje się tylko jeden pasek. Dzięki
ziggy
2
@ziggy testowany ciąg to „foobarbarfoo”. Jak widać, w łańcuchu znajdują się dwa foo i dwa paski.
skyfoot
4
Czy ktoś może wyjaśnić, kiedy może potrzebować grupy atomowej? Jeśli muszę dopasować tylko do pierwszej alternatywy, dlaczego miałbym podawać wiele alternatyw?
arviman
2
Lepsze wyjaśnienie grupy atomowej w tej odpowiedzi . Czy ktoś może edytować tutaj, aby wypełnić tę odpowiedź dydaktyczną?
Peter Krauss
5
Tylko uwaga, że ​​ta odpowiedź była niezbędna, kiedy skończyłem przy projekcie, który wymagał poważnych przeróbek wyrażeń regularnych. To doskonałe, zwięzłe wyjaśnienie rozejścia się.
Tom Coughlin
215

Lookarounds to asercje o zerowej szerokości. Sprawdzają regex (w prawo lub w lewo od bieżącej pozycji - w oparciu o przód lub tył), udaje się lub nie, gdy zostanie znalezione dopasowanie (na podstawie, czy jest ono dodatnie lub ujemne) i odrzuca dopasowaną część. Nie zużywają żadnych znaków - dopasowanie wyrażenia regularnego po nim (jeśli istnieje) rozpocznie się od tej samej pozycji kursora.

Przeczytaj regular-expression.info, aby uzyskać więcej informacji.

  • Pozytywne spojrzenie w przyszłość:

Składnia:

(?=REGEX_1)REGEX_2

Dopasuj tylko, jeśli REGEX_1 pasuje; po dopasowaniu REGEX_1 dopasowanie zostanie odrzucone, a wyszukiwanie REGEX_2 rozpocznie się od tej samej pozycji.

przykład:

(?=[a-z0-9]{4}$)[a-z]{1,2}[0-9]{2,3}

REGEX_1 [a-z0-9]{4}$pasuje do czterech znaków alfanumerycznych, po których następuje koniec linii.
REGEX_2 [a-z]{1,2}[0-9]{2,3}odpowiada jednej lub dwóm literom, po których następują dwie lub trzy cyfry.

REGEX_1 upewnia się, że długość ciągu rzeczywiście wynosi 4, ale nie zużywa żadnych znaków, więc wyszukiwanie REGEX_2 rozpoczyna się w tym samym miejscu. Teraz REGEX_2 upewnia się, że łańcuch pasuje do innych reguł. Bez przewidywania pasowałby do ciągów długości trzech lub pięciu.

  • Negatywne spojrzenie w przyszłość

Składnia:

(?!REGEX_1)REGEX_2

Dopasuj tylko, jeśli REGEX_1 nie pasuje; po sprawdzeniu REGEX_1 wyszukiwanie REGEX_2 rozpoczyna się w tej samej pozycji.

przykład:

(?!.*\bFWORD\b)\w{10,30}$

Część wyprzedzająca sprawdza FWORDciąg znaków i kończy się niepowodzeniem, jeśli go znajdzie. Jeśli nie zostanie znalezione FWORD, przeglądanie powiedzie się, a następna część sprawdza, czy długość łańcucha wynosi od 10 do 30 i czy zawiera tylko znaki słownea-zA-Z0-9_

Spojrzenie za siebie jest podobne do patrzenia w przyszłość: po prostu spogląda za bieżącą pozycję kursora. Niektóre smaki wyrażeń regularnych, takie jak javascript, nie obsługują asertywnych stwierdzeń. I większość smaków, które go obsługują (PHP, Python itp.) Wymagają, aby ta część z tyłu miała stałą długość.

  • Grupy atomowe w zasadzie odrzucają / zapominają kolejne tokeny w grupie, gdy token się dopasuje. Sprawdź tę stronę, aby zobaczyć przykłady grup atomowych
Amarghosh
źródło
po wyjaśnieniu nie wydaje się działać w javascript, /(?=source)hello/.exec("source...hummhellosource ") = null. Czy twoje wyjaśnienie jest prawidłowe?
Helin Wang
@HelinWang To wyjaśnienie jest poprawne. Twoje wyrażenie regularne oczekuje łańcucha, który jest jednocześnie źródłem i witaj!
Amarghosh
@jddxf Chcesz opracować?
Amarghosh,
@Amarghosh Zgadzam się z: „Sprawdzają regex (w prawo lub w lewo od bieżącej pozycji - w oparciu o przód lub tył), odnoszą sukcesy lub porażki po znalezieniu dopasowania (na podstawie tego, czy jest on dodatni czy ujemny) i odrzucają dopasowany część.". Więc lookahead powinien sprawdzić wyrażenie regularne w prawo od bieżącej pozycji, a składnia pozytywnego lookahead powinna wynosić x (? = Y)
jddxf
@Amarghosh (?=REGEX_1)REGEX_2pasuje tylko, jeśli REGEX_2przyjdzie później REGEX_1 ?
aandis
0

Gwałtownie się rozgląda.
Jak odróżnić lookahead i lookbehind? Wybierz się na 2-minutową wycieczkę ze mną:

(?=) - positive lookahead
(?<=) - positive lookbehind

Przypuszczać

    A  B  C #in a line

Teraz pytamy B, gdzie jesteś?
B ma dwa rozwiązania, które deklarują lokalizację:

Jeden, B ma A do przodu i ma C do drugiego
Dwa, B jest do przodu (z wyprzedzeniem) C i z tyłu (do tyłu) A.

Jak widzimy, oba rozwiązania są z tyłu i z przodu.
Regex to rozwiązanie drugie.

Rachunek różniczkowy
źródło