2009-09-03 15 views
14

Następujące wyrażenie wyszukuje tekst między podciągami FTW i ODP.Regex: co znaczy (?! ...)?

/FTW(((?!FTW|ODP).)+)ODP+/ 

Czego (?! ... ) zrobić?

+0

To Perl specyficzne (i pcre), prawda? – tylerl

+1

@tylerl: Dotyczy wszystkich smaków, które obsługują uprzedzenia: Perl, Python, PHP, .NET, Java, JavaScript, JGSoft, et al. –

Odpowiedz

22

(?!regex) jest zero-width negative lookahead. Będzie to sprawdzić znaki w bieżącym położeniu kursora i przekazania, testowanie, że robią NIE dopasować dostarczonego regex, a następnie powrócić kursor z powrotem do miejsca, gdzie to się zaczęło.

Cały regexp:

/ 
FTW   # Match Characters 'FTW' 
(   # Start Match Group 1 
    (   # Start Match Group 2 
    (?!FTW|ODP) # Ensure next characters are NOT 'FTW' or 'ODP', without matching 
    .    # Match one character 
)+   # End Match Group 2, Match One or More times 
)    # End Match Group 1 
OD   # Match characters 'OD' 
P+   # Match 'P' One or More times 
/

Więc - Polowanie na FTW, a następnie uchwycić podczas poszukiwania ODP+ do końca nasz łańcuch. Należy również upewnić się, że dane między FTW i ODP+ nie zawiera FTW lub ODP

+1

+1 za prawidłowe wyjaśnienie, w jaki sposób jest używany w dostarczonym regexie. –

7

To znaczy "nie następuje ...". Z technicznego punktu widzenia jest to tak zwane negative lookahead, ponieważ można zerknąć na to, co jest przed ciągiem, bez przechwytywania go. Jest klasą asercji o zerowej szerokości, co oznacza, że ​​takie wyrażenia nie przechwytują żadnej części wyrażenia.

18

Od perldoc:

A zerowej szerokości ujemny antycypowanego twierdzenie. Na przykład /foo(?!bar)/ pasuje do każdego wystąpienia „foo”, że nie następuje „bar”. Pamiętaj jednak, że patrzenie w przyszłość i patrzenie w przyszłość to NIE to samo. Nie możesz tego użyć, żeby się rozejrzeć.

Jeśli szukasz "paska", który nie jest poprzedzony "foo", /(?!foo)bar/ nie zrobi tego, co chcesz. To dlatego, że (?!foo) jest tylko, że następną rzeczą, nie może być „foo«--and nie jest to, że jest to «bar», więc»foobar” będzie pasował. Trzeba by zrobić coś takiego, jak /(?!foo)...bar/. Mówimy "jak", ponieważ jest przypadek twojego "bar", który nie ma trzech znaków przed nim. Można to objąć w ten sposób: /(?:(?!foo)...|^.{0,2})bar/. Czasami jest to jeszcze łatwiejsze po prostu powiedzieć:

if (/bar/ && $` !~ /foo$/) 
+0

Dla negatywnego wyglądu, jeśli parser obsługuje to, możesz po prostu użyć '(? Amber

+0

"Google to twój przyjaciel", jeśli masz pojęcie, jakich użyć terminów wyszukiwania. W każdym razie, czy nie chciałeś linkować do tego fragmentu? http://perldoc.perl.org/perlre.html#Look-Around-Asertions –

+0

w tym przypadku wydaje mi się, że jest to dość łatwe do zrozumienia dla google do dokumentacji regex. tak, dziękuję za poprawienie linku – mkoryak

0

'?' jest częścią "(?! ...)", oznacza to, że wszystko, co jest w środku NIE może pasować w tym miejscu.

3

Programista musi zostały wpisując zbyt szybko. Niektóre znaki we wzorze zostały odwrócone. Poprawione:

/WTF(((?!WTF|ODP).)+)ODP+/ 
+2

Haters: Daj spokój, trochę rozjaśnij. To był żart anagramowy, w którym niektórzy ludzie gardzą Regeksem. Chociaż nie jest "pomocny", nie miejmy tego zbyt mocno. – brianreavis

+0

+1 do walki z nienawiścią. – nilamo

+1

Odpowiedzi Jokey mogą wywoływać spadki nawet wtedy, gdy * są * pomocne; tak po prostu tutaj jest. Trochę się przyzwyczaja, ale myślę, że warto, pod względem ogólnej jakości witryny. –

2

Regex

/FTW(((?!FTW|ODP).)+)ODP+/ 
pierwszy

mecze FTW natychmiast następuje ani przez FTW ani przez ODP, to wszystkie kolejne znaki do pierwszego ODP (ale jeśli jest FTW gdzieś w nich nie będzie bez dopasowania), a następnie wszystkie litery P, które następują.

Więc w ciągu:

FTWFTWODPFTWjjFTWjjODPPPPjjODPPPjjj

będzie pasować śmiały część

FTWFTWODPFTWjj FTWjjODPPPP jjODPPPjjj

+0

Niewielki błąd w twojej logice, ponieważ asercja wyprzedzająca jest w grupie ed "+", dopasowuje dowolny tekst pomiędzy FTW .... ODP, który nie zawiera wewnątrz FTW ani ODP. – gnarf

+0

@gnarf ma rację: chciwy czy nie, to wyrażenie regularne nigdy nie będzie pasowało więcej niż jedno wystąpienie "FTW" lub "ODP". –

+0

Masz rację, mój błąd. Naprawiam to, by uniknąć nieporozumień przyszłych widzów. –