Jak zanegować całe wyrażenie regularne?

97

Na przykład mam wyrażenie regularne (ma|(t){1}). Pasuje mai tnie pasuje bla.

Chcę negować regex, więc to musi pasować blai nie mai t, dodając coś do tego regex . Wiem, że mogę pisać bla, ale rzeczywiste wyrażenie regularne jest bardziej złożone.

IAdapter
źródło
5
Nawiasem mówiąc, {1}jest całkowicie bezużyteczny. (Jeśli uważasz, że zapewnia to jakąś wartość, dlaczego nie napiszesz ((m{1}a{1}){1}|(t){1}){1}?)
tripleee

Odpowiedzi:

102

Użyj wykluczającego obejścia: (?!pattern)

Aby potwierdzić, że wzorzec jest zgodny, można użyć dodatnich lookarounds. Ujemne obejścia są odwrotne: są używane do stwierdzenia, że ​​wzorzec NIE pasuje. Niektóre smaki wspierają twierdzenia; niektórzy nakładają ograniczenia na patrzenie w tył itp.

Linki do regular-expressions.info

Zobacz też

Więcej przykładów

Są to próby znalezienia rozwiązań regex dla problemów z zabawkami jako ćwiczeń; powinny być pouczające, jeśli próbujesz nauczyć się różnych sposobów korzystania z obejrzeń (zagnieżdżanie ich, używanie ich do przechwytywania itp.):

smary wielogenowe
źródło
2
regular-expressions.info to cholernie dobre źródło wszystkich wyrażeń regularnych.
Freiheit
Co wszyscy mają wsparcie Lookaround ? Nie działa z grep.
Lazer
Pattern.compile("(?!(a.*b))").matcher("xab").matches()powinno być true, prawda?
Karl Richter
4
Wydaje mi się, że to nie w porządku, zobacz stackoverflow.com/questions/8610743/…, aby uzyskać poprawną alternatywę.
Karl Richter
57

Zakładając, że chcesz zabronić tylko ciągów, które całkowicie pasują do wyrażenia regularnego (tj. mmblaJest w porządku, ale mmnie jest), oto czego chcesz:

^(?!(?:m{2}|t)$).*$

(?!(?:m{2}|t)$)to negatywne spojrzenie w przód ; mówi „zaczynając od bieżącej pozycji, kilka następnych znaków nie jest mm lub t, po których następuje koniec ciągu”. Start anchor ( ^) na początku zapewnia, że ​​lookahead zostanie zastosowany na początku ciągu. Jeśli to się powiedzie, .*idzie dalej i zużywa ciąg.

FYI, jeśli używasz metody Java matches(), tak naprawdę nie potrzebujesz the ^i final $, ale nie wyrządzają one żadnej szkody. Wymagane jest jednak $wewnętrzne spojrzenie w przód.

Alan Moore
źródło
2
Najbardziej pomocną częścią tej odpowiedzi jest to, że musisz dodać .*na końcu swojego wyrażenia regularnego, w przeciwnym razie odrzuci każdy ciąg.
Rav
2
$ Wewnątrz na uprzedzona ujemnej, a .*na koniec są zarówno krytyczne bitów. Jak zawsze w przypadku RE, silny zestaw testów jednostkowych jest absolutnie niezbędny, aby uzyskać prawidłowy wynik. Ta odpowiedź jest w 100% poprawna.
Tom Dibble
1
\b(?=\w)(?!(ma|(t){1}))\b(\w*)

to jest dla danego wyrażenia regularnego.
\ b służy do znalezienia granicy słowa.
pozytywne spojrzenie w przyszłość (? = \ w) jest tutaj, aby uniknąć spacji.
negatywne spojrzenie w przyszłość na oryginalne wyrażenie regularne ma na celu zapobieganie jego dopasowaniom.
i na koniec (\ w *) ma przechwycić wszystkie pozostałe słowa.
grupa, w której będą przechowywane słowa, to grupa 3.
prosty (?! wzorzec) nie zadziała, ponieważ żaden podciąg będzie pasował
do prostego ^ (?! (?: m {2} | t) $). * $ będzie nie działa, ponieważ jego szczegółowość to pełne linie

Ofer Skulsky
źródło
0

Zastosuj to, jeśli używasz laravel.

Laravel ma not_regex, gdzie pole poddawane walidacji nie może pasować do podanego wyrażenia regularnego; używa preg_matchfunkcji PHP wewnętrznie.

'email' => 'not_regex:/^.+$/i'
DAVID AJAYI
źródło