Wiem, że można dopasować słowo, a następnie odwrócić dopasowania za pomocą innych narzędzi (np grep -v
.). Czy można jednak dopasować wiersze, które nie zawierają określonego słowa, np. hede
Używając wyrażenia regularnego?
Wejście:
hoho
hihi
haha
hede
Kod:
grep "<Regex for 'doesn't contain hede'>" input
Pożądane wyjście:
hoho
hihi
haha
regex
regex-negation
knaser
źródło
źródło
([^h]*(h([^e]|$)|he([^d]|$)|hed([^e]|$)))*
:? Pomysł jest prosty. Kontynuuj dopasowywanie, aż zobaczysz początek niechcianego ciągu, a następnie dopasuj tylko w przypadkach N-1, w których łańcuch jest niedokończony (gdzie N jest długością łańcucha). Te przypadki N-1 to „h, po którym następuje nie-e”, „on następuje po nie-d”, i „hed, po którym następuje nie-e”. Jeśli udało Ci się zaliczyć te przypadki N-1, nie udało Ci się dopasować niechcianego ciągu, więc możesz zacząć szukać[^h]*
ponownie^([^h]*(h([^e]|$)|he([^d]|$)|hed([^e]|$))?)*$
nie udaje się to, gdy wystąpienia „hede” są poprzedzone częściowymi wystąpieniami „hede”, na przykład w „hhede”.Odpowiedzi:
Pojęcie, że wyrażenie regularne nie obsługuje odwrotnego dopasowywania, nie jest do końca prawdziwe. Możesz naśladować to zachowanie, stosując negatywne zmiany:
Wyrażenie regularne powyżej będzie pasować do dowolnego łańcucha lub linii bez podziału linii, nie zawierających (pod) łańcucha „hede”. Jak wspomniano, wyrażenie regularne nie jest „dobre” w (lub powinno być), ale nadal jest możliwe.
A jeśli chcesz również dopasować znaki podziału linii, użyj modyfikatora DOT-ALL (
s
następujący wzór:lub użyj go w linii:
(gdzie
/.../
są ogranicznikami wyrażeń regularnych, tj. nie są częścią wzorca)Jeśli modyfikator DOT-ALL nie jest dostępny, możesz naśladować to samo zachowanie za pomocą klasy znaków
[\s\S]
:Wyjaśnienie
Łańcuch to tylko lista
n
znaków. Przed i po każdym znaku jest pusty ciąg. Zatem listan
znaków będzie miałan+1
puste ciągi. Rozważ ciąg"ABhedeCD"
:gdzie
e
są puste ciągi. Wyrażenie regularne(?!hede).
patrzy w przyszłość, aby zobaczyć, czy nie ma podłańcucha"hede"
, a jeśli tak jest (więc widać coś innego), wówczas.
(kropka) będzie pasować do dowolnego znaku z wyjątkiem podziału linii. Rozejrzenia są również nazywane asercjami o zerowej szerokości, ponieważ nie zużywają żadnych znaków. Twierdzą tylko / potwierdzają coś.Tak więc, w moim przykładzie, każdy pusty łańcuch jest najpierw sprawdzany, czy nie ma
"hede"
przed nim znaku, zanim znak zostanie zużyty przez.
kropkę. Regex(?!hede).
będzie zrobić tylko raz, więc jest owinięty w grupie, a powtórzony zero lub więcej razy:((?!hede).)*
. Wreszcie, początek i koniec wejścia są zakotwiczone, aby mieć pewność, że całe wejście zostanie wykorzystane:^((?!hede).)*$
Jak widać, wejście
"ABhedeCD"
nie powiedzie się, ponieważ one3
, regex(?!hede)
zawiedzie ( jest"hede"
przed nami!).źródło
grep
, o których wspomina OP) z obsługą wyrażeń regularnych, wszystkie mają funkcje, które sprawiają, że są nieregularne w sensie teoretycznym.^\(\(hede\)\@!.\)*$
Zauważ, że rozwiązanie nie zaczyna się od „hede” :
jest ogólnie znacznie wydajniejszy niż rozwiązanie, które nie zawiera „hede” :
Pierwszy sprawdza „hede” tylko na pierwszej pozycji ciągu wejściowego, a nie na każdej pozycji.
źródło
(.*)(?<!hede)$
. Wersja @Nyerguds również działałaby, ale całkowicie pomija punkt wydajności, o którym mowa w odpowiedzi.^((?!hede).)*$
? Czy nie jest bardziej wydajny w użyciu^(?!.*hede).*$
? Robi to samo, ale w mniejszej liczbie krokówJeśli używasz go tylko do grep, możesz użyć,
grep -v hede
aby uzyskać wszystkie wiersze, które nie zawierają hede.ETA. Ponowne przeczytanie pytania
grep -v
jest prawdopodobnie tym, co rozumiesz przez „opcje narzędzi”.źródło
grep -v -e hede -e hihi -e ...
grep -v "hede\|hihi"
:)grep -vf pattern_file file
egrep
albogrep -Ev "hede|hihi|etc"
uniknąć niezręcznej ucieczkę.Odpowiedź:
Wyjaśnienie:
^
początek ciągu,(
grupowanie i przechwytywanie do \ 1 (0 lub więcej razy (dopasowanie największej możliwej ilości)),(?!
spójrz w przyszłość, aby zobaczyć, czy nie ma,hede
twój sznurek,)
koniec patrzenia w przód,.
dowolny znak oprócz \ n,)*
koniec \ 1 (Uwaga: ponieważ używasz kwantyfikatora w tym przechwytywaniu, tylko OSTATNIE powtórzenie przechwyconego wzoru zostanie zapisane w \ 1)$
przed opcjonalnym \ n, i koniec łańcuchaźródło
^((?!DSAU_PW8882WEB2|DSAU_PW8884WEB2|DSAU_PW8884WEB).)*$
'Podane odpowiedzi są w porządku, tylko akademicki punkt:
Wyrażenia regularne w znaczeniu teoretycznych informatyki NIE MOGĄ tego robić w ten sposób. Dla nich musiało to wyglądać mniej więcej tak:
To tylko pasuje PEŁNY. Robienie tego w meczach podrzędnych byłoby jeszcze bardziej niezręczne.
źródło
(hede|Hihi)
”? (To może pytanie do CS.)Jeśli chcesz, aby test wyrażenia regularnego zakończył się niepowodzeniem tylko wtedy, gdy cały ciąg znaków jest zgodny, następujące działania będą działać:
np. Jeśli chcesz zezwolić na wszystkie wartości oprócz „foo” (tzn. „foofoo”, „barfoo” i „foobar” przejdą, ale „foo” nie powiedzie się), użyj:
^(?!foo$).*
Oczywiście, jeśli sprawdzasz dokładność równości, lepszym ogólnym rozwiązaniem w tym przypadku jest sprawdzenie równości ciągów, tj
Możesz nawet umieścić negację poza testem, jeśli potrzebujesz funkcji wyrażenia regularnego (w tym przypadku rozróżnianie wielkości liter i dopasowanie zakresu):
Rozwiązanie wyrażenia regularnego u góry tej odpowiedzi może być jednak pomocne w sytuacjach, w których wymagany jest pozytywny test wyrażenia regularnego (być może przez API).
źródło
" hede "
?\s
dyrektywa pasuje do jednej spacji^(?!\s*hede\s*$).*
FWIW, ponieważ języki regularne (zwane również językami wymiernymi) są zamknięte z dopełnianiem, zawsze można znaleźć wyrażenie regularne (zwane także wyrażeniem wymiernym), które neguje inne wyrażenie. Ale niewiele narzędzi to implementuje.
Vcsn obsługuje ten operator (co oznacza
{c}
postfiks).Najpierw zdefiniować typ wyrażeń: Etykiety są list (
lal_char
), aby wybrać za
, abyz
na przykład (definiowanie alfabetu podczas pracy z uzupełnianie jest oczywiście bardzo ważne), a „wartość” obliczana dla każdego słowa jest po prostu logiczna :true
słowo jest akceptowanefalse
, odrzucone.W Pythonie:
następnie wpisz wyrażenie:
przekonwertuj to wyrażenie na automat:
na koniec przekonwertuj ten automat z powrotem na proste wyrażenie.
gdzie
+
jest zwykle oznaczane|
,\e
oznacza puste słowo i[^]
jest zwykle zapisywane.
(dowolny znak). Więc przy odrobinie przepisywania()|h(ed?)?|([^h]|h([^e]|e([^d]|d([^e]|e.)))).*
.Możesz zobaczyć ten przykład tutaj i wypróbować Vcsn online tam .
źródło
|
nie będzie ładnie grało.'^(()|h(ed?)?|([^h]|h([^e]|e([^d]|d([^e]|e.)))).*)$'
.Oto dobre wyjaśnienie, dlaczego nie jest łatwo zanegować arbitralne wyrażenie regularne. Muszę jednak zgodzić się z innymi odpowiedziami: jeśli jest to coś innego niż pytanie hipotetyczne, to wyrażenie regularne nie jest tutaj właściwym wyborem.
źródło
W przypadku negatywnego spojrzenia wyrażenie regularne może pasować do czegoś, co nie zawiera określonego wzorca. Odpowiada na to i wyjaśnia Bart Kiers. Świetne wyjaśnienie!
Jednak z odpowiedzią Barta Kiersa część lookahead przetestuje od 1 do 4 znaków z przodu, dopasowując dowolny pojedynczy znak. Możemy tego uniknąć i pozwolić, aby część z wyprzedzeniem sprawdziła cały tekst, upewniając się, że nie ma „hede”, a wtedy normalna część (. *) Może zjeść cały tekst jednocześnie.
Oto ulepszone wyrażenie regularne:
Zauważ, że (*?) Leniwy kwantyfikator w negatywnej części z wyprzedzeniem jest opcjonalny, możesz zamiast tego użyć (*) chciwego kwantyfikatora, w zależności od twoich danych: jeśli „hede” występuje i na początku połowy tekstu, leniwy kwantyfikator może bądź szybszy; w przeciwnym razie chciwy kwantyfikator będzie szybszy. Jeśli jednak „hede” się nie pojawi, oba będą równe powolne.
Oto kod demo .
Aby uzyskać więcej informacji o lookahead, zapoznaj się ze świetnym artykułem: Mastering Lookahead and Lookbehind .
Sprawdź także RegexGen.js , generator wyrażeń regularnych JavaScript, który pomaga konstruować złożone wyrażenia regularne. Za pomocą RegexGen.js możesz zbudować wyrażenie regularne w bardziej czytelny sposób:
źródło
^(?!.*(str1|str2)).*$
^(?!.*?(?:str1|str2)).*$
w zależności od danych. Dodano,?:
ponieważ nie musimy tego robić.Benchmarki
Postanowiłem ocenić niektóre z przedstawionych Opcji i porównać ich wydajność, a także użyć nowych funkcji. Benchmarking w .NET Regex Engine: http://regexhero.net/tester/
Tekst testu:
Pierwsze 7 wierszy nie powinno się zgadzać, ponieważ zawierają wyszukiwane wyrażenie, a dolne 7 wierszy powinno pasować!
Wyniki:
Wyniki to Iteracje na sekundę jako mediana 3 przebiegów - Większa liczba = lepsza
Ponieważ .NET nie obsługuje działań Czasowniki (* FAIL itp.), Nie mogłem przetestować rozwiązań P1 i P2.
Podsumowanie:
Próbowałem przetestować większość proponowanych rozwiązań, niektóre Optymalizacje są możliwe dla niektórych słów. Na przykład, jeśli dwie pierwsze litery szukanego ciągu nie są takie same, odpowiedź 03 można rozszerzyć, aby
^(?>[^R]+|R+(?!egex Hero))*$
uzyskać niewielki wzrost wydajności.Ale ogólnie najbardziej czytelnym i pod względem wydajności najszybszym rozwiązaniem wydaje się być 05 przy użyciu instrukcji warunkowej lub 04 z dodatnim kwantyfikatorem. Myślę, że rozwiązania Perla powinny być jeszcze szybsze i bardziej czytelne.
źródło
^(?!.*hede)
. /// Również prawdopodobnie lepiej uszeregować wyrażenia dla dopasowanego korpusu i niepasującego korpusu osobno, ponieważ zwykle jest tak, że większość pasujących wierszy lub większość linii nie.Nie regex, ale uznałem, że logiczne i użyteczne jest używanie seryjnych grepów z rurką w celu wyeliminowania hałasu.
na przykład. przeszukać plik konfiguracyjny Apache bez wszystkich komentarzy
i
Logika seryjnego grepa to (nie komentarz) i (pasuje do reż)
źródło
grep -v
good_stuff #comment_stuff
dzięki temu unikniesz testowania z wyprzedzeniem każdej pozycji:
odpowiednik (dla .net):
Stara odpowiedź:
źródło
/^[^h]*(?:h+(?!ede)[^h]*)*$/
Wyżej wspomniane
(?:(?!hede).)*
jest świetne, ponieważ można je zakotwiczyć.W tym przypadku wystarczyłyby:
W tym uproszczeniu można dodać klauzule „ORAZ”:
źródło
Oto jak bym to zrobił:
Dokładne i bardziej wydajne niż inne odpowiedzi. Implementuje technikę efektywności „rozwijania pętli” Friedla i wymaga znacznie mniejszego cofania.
źródło
Jeśli chcesz dopasować znak, aby zanegować słowo podobne do negacji klasy znaków:
Na przykład ciąg:
Nie używaj:
Posługiwać się:
Uwaga
"(?!bbb)."
nie jest ani lookbehind ani lookahead, jest lookcurrent, na przykład:źródło
(?!
). Dodatni prefiks(?=
lookahead byłby, podczas gdy odpowiadające prefiksy lookhind byłyby odpowiednio(?<!
i(?<=
. Lookahead oznacza, że czytasz kolejne postacie (stąd „naprzód”) bez ich konsumowania. Lookbehind oznacza, że sprawdzasz postacie, które zostały już zużyte.Moim zdaniem, bardziej czytelny wariant najwyższej odpowiedzi:
Zasadniczo „dopasuj na początku wiersza, jeśli i tylko wtedy, gdy nie ma w nim„ hede ”- więc wymaganie przełożyło się prawie bezpośrednio na wyrażenie regularne.
Oczywiście istnieje wiele wymagań dotyczących awarii:
Szczegóły: Kotwica ^ zapewnia, że silnik regex nie powtórzy dopasowania w każdym miejscu ciągu, co pasowałoby do każdego łańcucha.
Kotwica ^ na początku ma oznaczać początek linii. Narzędzie grep dopasowuje każdą linię pojedynczo, w kontekstach, w których pracujesz z ciągiem wielowierszowym, możesz użyć flagi „m”:
lub
źródło
OP nie określił ani nie Tagwskazał kontekstu (języka programowania, edytora, narzędzia), w którym będzie używany Regex.
Dla mnie czasami muszę to zrobić podczas edytowania pliku za pomocą
Textpad
.Textpad
obsługuje niektóre Regex, ale nie obsługuje lookahead ani lookbeind, więc zajmuje to kilka kroków.Jeśli chcę zachować wszystkie wiersze, które NIE zawierają łańcucha
hede
, zrobiłbym to w ten sposób:Teraz masz oryginalny tekst ze wszystkimi wierszami zawierającymi ciąg znaków
hede
.Jeśli chcę zrobić coś innego tylko w wierszach, które NIE zawierają łańcucha
hede
, zrobiłbym to w ten sposób:źródło
Ponieważ nikt inny nie udzielił bezpośredniej odpowiedzi na zadane pytanie , zrobię to.
Odpowiedź jest taka, że w POSIX
grep
niemożliwe jest dosłownie spełnienie tego żądania:Powodem jest to, że POSIX
grep
jest wymagany tylko do pracy z podstawowymi wyrażeniami regularnymi , które po prostu nie są wystarczające do wykonania tego zadania (nie są w stanie analizować zwykłych języków z powodu braku naprzemienności i nawiasów).Jednak GNU
grep
implementuje rozszerzenia, które na to pozwalają. W szczególności\|
jest operatorem naprzemiennym w implementacji BREU przez GNU\(
i\)
jest nawiasami. Jeśli silnik wyrażeń regularnych obsługuje naprzemiennie, wyrażenia z nawiasami ujemnymi, nawiasy i gwiazdę Kleene i jest w stanie zakotwiczyć na początku i na końcu łańcucha, to wszystko, czego potrzebujesz do tego podejścia. Zauważ jednak, że zestawy ujemne[^ ... ]
są bardzo wygodne oprócz tych, ponieważ w przeciwnym razie musisz je zastąpić wyrażeniem formy,(a|b|c| ... )
która zawiera listę wszystkich znaków, których nie ma w zestawie, co jest niezwykle żmudne i zbyt długie, tym bardziej, jeśli cały zestaw znaków to Unicode.W przypadku GNU
grep
odpowiedzią byłoby:(znaleziono z Graalem i kilkoma dalszymi optymalizacjami wykonanymi ręcznie).
Możesz także użyć narzędzia, które implementuje Rozszerzone wyrażenia regularne , na przykład
egrep
, aby pozbyć się odwrotnych ukośników:Oto skrypt do jego przetestowania (pamiętaj, że generuje plik
testinput.txt
w bieżącym katalogu):W moim systemie drukuje:
zgodnie z oczekiwaniami.
Dla zainteresowanych szczegółami zastosowana technika polega na konwersji wyrażenia regularnego pasującego do słowa na automat skończony, a następnie odwróceniu automatu poprzez zmianę każdego stanu akceptacji na brak akceptacji i odwrotnie, a następnie konwersję wynikowego FA z powrotem na wyrażenie regularne.
W końcu, jak wszyscy zauważyli, jeśli silnik wyrażeń regularnych obsługuje negatywne spojrzenie, to znacznie upraszcza to zadanie. Na przykład z GNU grep:
Aktualizacja: Niedawno znalazłem doskonałą bibliotekę FormalTheory Kendalla Hopkinsa , napisaną w PHP, która zapewnia funkcjonalność podobną do Graala. Używając go i napisanego przeze mnie prostownika, byłem w stanie napisać internetowy generator negatywnych wyrażeń regularnych, podając frazę wejściową (obecnie obsługiwane są tylko znaki alfanumeryczne i spacje): http://www.formauri.es/personal/ pgimeno / misc / non-match-regex /
Do
hede
wyjścia:co jest równoważne z powyższym.
źródło
Od czasu wprowadzenia ruby-2.4.1 możemy używać nowego nieobecnego operatora w wyrażeniach regularnych Ruby
z oficjalnego dokumentu
Tak więc w twoim przypadku
^(?~hede)$
robi to za Ciebieźródło
Przez czasownik PCRE
(*SKIP)(*F)
To całkowicie pomija linię, która zawiera dokładny ciąg
hede
i pasuje do wszystkich pozostałych linii.PRÓBNY
Wykonanie części:
Rozważmy powyższe wyrażenie regularne, dzieląc je na dwie części.
Część przed
|
symbolem. Części nie należy dopasowywać .Część po
|
symbolu. Część powinna być dopasowana .CZĘŚĆ 1
Silnik Regex rozpocznie wykonywanie od pierwszej części.
Wyjaśnienie:
^
Zapewnia, że jesteśmy na początku.hede
Dopasowuje ciąghede
$
Zapewnia, że jesteśmy na końcu linii.Tak więc linia zawierająca ciąg znaków
hede
byłaby dopasowana. Gdy silnik wyrażenia regularnego zobaczy następujący czasownik(*SKIP)(*F)
( uwaga: możesz napisać(*F)
jako(*FAIL)
), przeskakuje i powoduje niepowodzenie dopasowania.|
nazywany zmianą lub logicznym operatorem OR dodanym obok czasownika PCRE, którego inturn pasuje do wszystkich granic istniejących między każdym znakiem na wszystkich liniach, z wyjątkiem tego, że wiersz zawiera dokładny ciąghede
. Zobacz demo tutaj . Oznacza to, że próbuje dopasować znaki z pozostałego ciągu. Teraz wyrażenie regularne w drugiej części zostanie wykonane.CZĘŚĆ 2
Wyjaśnienie:
^
Zapewnia, że jesteśmy na początku. tzn. pasuje do wszystkich początków linii oprócz tej whede
linii. Zobacz demo tutaj ..*
W trybie wielowierszowym pasowałby do.
każdego znaku oprócz znaków nowego wiersza lub znaków powrotu karetki. I*
powtórzyłby poprzedni znak zero lub więcej razy. Więc.*
pasowałby do całej linii. Zobacz demo tutaj .Hej, dlaczego dodałeś. * Zamiast. +?
Ponieważ
.*
pasowałby do pustej linii, ale.+
nie pasuje do pustej. Chcemy dopasować wszystkie linie, z wyjątkiem tegohede
, że na wejściu mogą występować puste linie. więc musisz użyć.*
zamiast.+
..+
powtórzy poprzedni znak jeden lub więcej razy. Zobacz.*
pasuje do pustej linii tutaj .$
Zakotwiczenie końca linii nie jest tutaj konieczne.źródło
Może być łatwiejsze do utrzymania do dwóch wyrażeń regularnych w kodzie, jednego do wykonania pierwszego dopasowania, a następnie, jeśli się zgadza, uruchom drugie wyrażenie regularne, aby sprawdzić przypadki odstające, które chcesz na przykład zablokować,
^.*(hede).*
a następnie mieć odpowiednią logikę w kodzie.OK, przyznaję, że tak naprawdę nie jest to odpowiedź na wysłane pytanie i może również wymagać nieco więcej przetwarzania niż jednego wyrażenia regularnego. Ale dla programistów, którzy przybyli tutaj, szukając szybkiej naprawy awaryjnej dla przypadku odstającego, to rozwiązanie nie powinno zostać przeoczone.
źródło
TXR Język obsługuje regex negację.
Bardziej skomplikowany przykład: dopasuj wszystkie linie, które zaczynają się
a
i kończąz
, ale nie zawierają podłańcuchahede
:Negacja Regex sama w sobie nie jest szczególnie przydatna, ale gdy masz również skrzyżowanie, sprawy stają się interesujące, ponieważ masz pełny zestaw operacji na zestawach boolowskich: możesz wyrazić „zestaw, który pasuje do tego, z wyjątkiem rzeczy, które pasują do tego”.
źródło
Inną opcją jest dodanie pozytywnego spojrzenia w przyszłość i sprawdzenie, czy
hehe
jest gdzieś w wierszu wprowadzania, wtedy negujemy to, używając wyrażenia podobnego do:z granicami słów.
Wyrażenie to wyjaśniono w prawym górnym panelu strony regex101.com , jeśli chcesz je zbadać / uprościć / zmodyfikować, a pod tym linkiem możesz zobaczyć, jak będzie pasował do niektórych przykładowych danych wejściowych, jeśli chcesz.
RegEx Circuit
jex.im wizualizuje wyrażenia regularne:
źródło
Poniższa funkcja pomoże ci uzyskać pożądaną wydajność
źródło
^ ((?! hede).) * $ jest eleganckim rozwiązaniem, z wyjątkiem tego, że zużywa znaki, nie będziesz w stanie połączyć go z innymi kryteriami. Powiedzmy na przykład, że chcesz sprawdzić, czy nie ma „hede” i „haha”. To rozwiązanie działałoby, ponieważ nie zużywa znaków:
^ (?!. \ bhede \ b) (? =. \ bhaha \ b)
źródło
Jak używać czasowników kontrolnych cofania PCRE, aby dopasować wiersz nie zawierający słowa
Oto metoda, której wcześniej nie widziałem:
Jak to działa
Najpierw próbuje znaleźć „hede” gdzieś w linii. Jeśli się powiedzie, w tym momencie
(*COMMIT)
mówi silnikowi, aby nie tylko nie cofał się w przypadku awarii, ale także nie próbował w tym przypadku dokonywać dalszych dopasowań. Następnie próbujemy dopasować coś, co nie może być zgodne (w tym przypadku,^
).Jeśli wiersz nie zawiera „hede”, wówczas druga alternatywa, pusty wzorzec, z powodzeniem dopasowuje ciąg tematu.
Ta metoda nie jest bardziej wydajna niż negatywne spojrzenie w przyszłość, ale pomyślałem, że po prostu ją tu wrzucę, na wypadek, gdyby ktoś uznał ją za sprytną i znalazł zastosowanie w innych, bardziej interesujących aplikacjach.
źródło
Prostszym rozwiązaniem jest użycie operatora non !
Twoja instrukcja if będzie musiała pasować do „zawiera”, a nie do „wyklucza”.
Wierzę, że projektanci RegEx przewidzieli użycie nie operatorów.
źródło
Być może znajdziesz to w Google podczas próby napisania wyrażenia regularnego, które jest w stanie dopasować segmenty linii (w przeciwieństwie do całych linii), które nie zawierają podłańcucha. Zajęło mi to trochę czasu, aby dowiedzieć się, więc podzielę się:
Podany ciąg:
<span class="good">bar</span><span class="bad">foo</span><span class="ugly">baz</span>
Chcę dopasować
<span>
tagi, które nie zawierają podłańcucha „zły”./<span(?:(?!bad).)*?>
będzie pasować<span class=\"good\">
i<span class=\"ugly\">
.Zauważ, że istnieją dwa zestawy (warstwy) nawiasów:
Demo w Ruby:
źródło
Za pomocą ConyEdit można użyć wiersza polecenia,
cc.gl !/hede/
aby uzyskać wiersze, które nie zawierają dopasowania wyrażenia regularnego, lub użyć wiersza polecenia,cc.dl /hede/
aby usunąć wiersze zawierające dopasowanie wyrażenia regularnego. Mają ten sam wynik.źródło
Chciałem dodać kolejny przykład, jeśli próbujesz dopasować całą linię, która zawiera ciąg X , ale nie zawiera również ciągu Y. .
Na przykład, powiedzmy, że chcemy sprawdzić, czy nasz adres URL / ciąg znaków zawiera „ smaczne smakołyki ”, o ile nie zawiera nigdzie „ czekolady ”.
Ten wzorzec wyrażenia regularnego działałby (działa również w JavaScript)
(na przykład globalne flagi wieloliniowe)
Interaktywny przykład: https://regexr.com/53gv4
mecze
(Te adresy URL zawierają „smaczne smakołyki”, a także nie zawierają „czekolady”)
Nie pasuje
(Te adresy URL zawierają gdzieś „czekoladę” - więc nie będą pasować, nawet jeśli zawierają „smaczne smakołyki”)
źródło