Dopasuj wszystko oprócz określonych ciągów


119

Wiem, że poniższe wyrażenie regularne będzie pasowało do wyrażenia „czerwony”, „zielony” lub „niebieski”.

red|green|blue

Czy istnieje prosty sposób dopasowania wszystkiego oprócz kilku określonych ciągów?


1
Nie wszystkie odmiany wyrażeń regularnych to umożliwiają. W jakim środowisku pracujesz? Jawa? Perl? .NETTO? Jakaś biblioteka wyrażeń regularnych C / C ++? RDBMS?
FrustratedWithFormsDesigner

8
Nie mówisz, czego chcesz, ale możesz po prostu odwrócić sens operacji „dopasuj”. To nie pomoże, jeśli próbujesz wyodrębnić niepasujące części, ale aby sprawdzić, czy nie ma wykluczonego ciągu, zadziała: if (!s.match(/red|green|blue/)) ... Uwaga: Wiem, że OP nie określa języka / struktury, więc powyższy przykład należy traktować jako ogólny przykład, a nie nakazowy.
tvanfosson

Odpowiedzi:


154

Jeśli chcesz się upewnić, że sznurek nie jest ani czerwony, ani zielony, ani niebieski, odpowiedź Caskey jest taka. Często jednak pożądane jest upewnienie się, że linia nie zawiera w żadnym miejscu koloru czerwonego, zielonego ani niebieskiego. W tym celu zakotwicz wyrażenie regularne za pomocą ^i uwzględnij .*w negatywnym wyglądzie:

^(?!.*(red|green|blue))

Załóżmy też, że chcesz wiersze zawierające słowo „silnik”, ale bez żadnego z tych kolorów:

^(?!.*(red|green|blue)).*engine

Możesz pomyśleć, że możesz uwzględnić to .*na początku wyrażenia regularnego:

^.*(?!red|green|blue)engine     # Does not work

ale nie możesz. Musisz mieć oba wystąpienia .*, aby działało.


48

Zależy od języka, ale generalnie są twierdzenia negatywne, które można umieścić w ten sposób:

(?!red|green|blue)

(Dzięki za poprawkę składni, powyższe dotyczy poprawnych Java i Perl, YMMV)


2
@caskey, Pełna odpowiedź to połączenie moje i twojego. Jeśli chcesz je połączyć, usunę moje.
Wayne Conrad

14
Ta odpowiedź byłaby o wiele bardziej przydatna, gdybyś ją trochę wyjaśnił. Na przykład: co oznacza „?” i "!" oznaczać? Dlaczego potrzebujesz grup przechwytywania?
Lii

To także poprawny Python.
Joe Mornin

właśnie użyłem tego z biblioteką regEx Delphi i działa tylko tak: ^ (?! red | green | blue). Dotyczy to również testowania w witrynie regex101.com . Czy powyższa literówka nie zawiera ^, czy faktycznie działa tak w Javie / Perl / Pythonie ..?
Peter

33

Dopasowywanie wszystkiego oprócz danych ciągów

Jeśli chcesz dopasować cały ciąg, w którym chcesz dopasować wszystko oprócz niektórych ciągów, możesz to zrobić w następujący sposób:

^(?!(red|green|blue)$).*$

Oznacza to, że rozpocznij dopasowanie od początku ciągu, w którym nie może zaczynać się i kończyć kolorem czerwonym, zielonym lub niebieskim, i dopasowywać wszystko inne do końca ciągu.

Możesz spróbować tutaj: https://regex101.com/r/rMbYHz/2

Zauważ, że działa to tylko z silnikami regex, które obsługują negatywne lookahead .


23

Nie potrzebujesz negatywnego spojrzenia w przód. Oto działający przykład:

/([\s\S]*?)(red|green|blue|)/g

Opis:

  • [\s\S] - dopasuj dowolny znak
  • * - mecz od 0 do nieograniczonej liczby z poprzedniej grupy
  • ? - dopasuj jak najmniej
  • (red|green|blue|) - dopasuj jedno z tych słów lub nic
  • g - powtórz wzór

Przykład:

whiteredwhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredwhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredredgreenredgreenredgreenredgreenredgreenbluewhiteredbluewhiteredbluewhiteredbluewhiteredbluewhiteredwhite

Będzie:

whitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhite

Sprawdź to: regex101.com


4
Możesz drastycznie zmniejszyć liczbę kroków, zamieniając [\ s \ S] na kropkę. Byłem bardzo zdezorientowany, dlaczego pozornie każdy inny przykład oddaje każde słowo z osobna. W ten sposób jest nieco więcej kroków regex, ale wymaga znacznie mniej przetwarzania końcowego.
Zatronium

3
ale to nie robi dopasowywania (sprawdzania poprawności tekstu), po prostu usuwa określony tekst podczas podstawiania.
Marek R

To rozwiązanie nie wyświetli ostatniego fragmentu tekstu po znanych słowach. Nie ma więc potrzeby porównywania prędkości, po prostu jest źle.
Wiktor Stribiżew

@ WiktorStribiżew naprawiono.
hlcs

10

Miałem to samo pytanie, proponowane rozwiązania prawie działały, ale miały jakiś problem. Ostatecznie wyrażenie regularne, którego użyłem, to:

^(?!red|green|blue).*

Przetestowałem to w Javascript i .NET.

. * nie powinno być umieszczane wewnątrz ujemnego lookahead w ten sposób: ^ (?!. * red | green | blue) albo spowodowałoby to, że pierwszy element zachowywałby się inaczej niż reszta (tj. „inny czerwony” nie zostałby dopasowany, podczas gdy " inny zielony ”)


3

Dopasowanie dowolnego tekstu poza tymi, które pasują do wzorca, zwykle uzyskuje się przez podzielenie ciągu za pomocą wzorca wyrażenia regularnego .

Przykłady :

  • - Regex.Split(text, @"red|green|blue")lub, aby pozbyć się pustych wartości Regex.Split(text, @"red|green|blue").Where(x => !string.IsNullOrEmpty(x))(patrz demo )
  • - Regex.Split(text, "red|green|blue")lub, aby usunąć puste elementy Regex.Split(text, "red|green|blue").Where(Function(s) Not String.IsNullOrWhitespace(s))(zobacz demo lub to demo, w którym obsługiwane jest LINQ)
  • - text.split(/red|green|blue/)(nie ma potrzeby używania gtutaj modyfikatora!) (aby pozbyć się pustych wartości, użyj text.split(/red|green|blue/).filter(Boolean)), zobacz demo
  • - text.split("red|green|blue")lub - aby zachować wszystkie końcowe puste elementy - użyj text.split("red|green|blue", -1)lub, aby usunąć wszystkie puste elementy, użyj więcej kodu, aby je usunąć (zobacz demo )
  • - Podobnie jak w Javie,, text.split(/red|green|blue/)aby uzyskać użycie wszystkich elementów końcowych text.split(/red|green|blue/, -1)i usunąć wszystkie puste elementy text.split(/red|green|blue/).findAll {it != ""})(patrz demo )
  • - text.split(Regex("red|green|blue"))lub, aby usunąć puste elementy, użyj text.split(Regex("red|green|blue")).filter{ !it.isBlank() }, zobacz demo
  • - text.split("red|green|blue")lub aby zachować wszystkie końcowe puste elementy, użyj text.split("red|green|blue", -1)i, aby usunąć wszystkie puste elementy, użyj text.split("red|green|blue").filter(_.nonEmpty)(zobacz demo )
  • - text.split(/red|green|blue/), aby pozbyć się pustych wartości, użyj .split(/red|green|blue/).reject(&:empty?)(i aby uzyskać zarówno początkowe, jak i końcowe puste elementy, użyj -1jako drugiego argumentu, .split(/red|green|blue/, -1)) (patrz demo )
  • - my @result1 = split /red|green|blue/, $text;lub ze wszystkimi końcowymi pustymi pozycjami my @result2 = split /red|green|blue/, $text, -1;, lub bez żadnych pustych pozycji my @result3 = grep { /\S/ } split /red|green|blue/, $text;(patrz demo )
  • - preg_split('~red|green|blue~', $text)lub preg_split('~red|green|blue~', $text, -1, PREG_SPLIT_NO_EMPTY)aby nie wyświetlać żadnych pustych pozycji (patrz demo )
  • - re.split(r'red|green|blue', text)lub, aby usunąć puste elementy, list(filter(None, re.split(r'red|green|blue', text)))(zobacz demo )
  • - Użyj regexp.MustCompile("red|green|blue").Split(text, -1), a jeśli chcesz usunąć puste elementy, użyj tego kodu . Zobacz demo Go .

UWAGA : Jeśli wzorce zawierają grupy przechwytywania , funkcje / metody podziału wyrażeń regularnych mogą zachowywać się inaczej, również w zależności od dodatkowych opcji. W takim przypadku należy zapoznać się z odpowiednią dokumentacją metody podziału.


0

Wszystkie oprócz słowa „czerwony”

var href = '(text-1) (red) (text-3) (text-4) (text-5)';

var test = href.replace(/\((\b(?!red\b)[\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Wszystkie oprócz słowa „czerwony”

var href = '(text-1) (frede) (text-3) (text-4) (text-5)';

var test = href.replace(/\(([\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = p1.replace(/red/g, '');
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.