Wie kann man den gesamten regulären Ausdruck negieren?

95

Ich habe zum Beispiel eine Regex (ma|(t){1}). Es passt maund tund passt nicht bla.

Ich mag die Regex negieren, so muss es passen blaund nicht maund t, von etwas zu diesem regex Zugabe . Ich weiß, dass ich schreiben kann bla, der eigentliche reguläre Ausdruck ist jedoch komplexer.

IAdapter
quelle
4
Nebenbei bemerkt, {1}ist völlig nutzlos. (Wenn Sie denken, dass es einen Wert bietet, warum schreiben Sie nicht ((m{1}a{1}){1}|(t){1}){1}?)
Tripleee

Antworten:

100

Verwenden Sie einen negativen Lookaround: (?!pattern)

Positive Lookarounds können verwendet werden, um zu bestätigen, dass ein Muster übereinstimmt. Negative Lookarounds sind das Gegenteil: Sie werden verwendet, um zu behaupten, dass ein Muster NICHT übereinstimmt. Einige Geschmacksrichtungen unterstützen Behauptungen; Einige schränken das Aussehen usw. ein.

Links zu regulär-expressions.info

Siehe auch

Mehr Beispiele

Dies sind Versuche, Regex-Lösungen für Spielzeugprobleme als Übungen zu finden. Sie sollten lehrreich sein, wenn Sie lernen möchten, wie Sie Lookarounds verwenden können (Verschachteln, Erfassen usw.):

Polygenschmierstoffe
quelle
2
Regular-expressions.info ist eine verdammt gute Ressource für alle Dinge, die Regex betreffen.
Freiheit
Was haben alle Lookaround- Unterstützung? Funktioniert nicht mit grep.
Lazer
Pattern.compile("(?!(a.*b))").matcher("xab").matches()sollte sein true, richtig?
Karl Richter
4
Ich scheine so nicht richtig zu sein, siehe stackoverflow.com/questions/8610743/… für eine korrekte Alternative.
Karl Richter
56

Angenommen, Sie möchten nur Zeichenfolgen verbieten, die vollständig mit dem regulären Ausdruck übereinstimmen (dh in mmblaOrdnung sind, aber mmnicht), dann möchten Sie Folgendes:

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

(?!(?:m{2}|t)$)ist ein negativer Lookahead ; es heißt "ab der aktuellen Position sind die nächsten Zeichen nicht mm oder t, gefolgt vom Ende der Zeichenfolge." Der Startanker ( ^) am Anfang stellt sicher, dass der Lookahead am Anfang der Zeichenfolge angewendet wird. Wenn dies erfolgreich ist, .*geht der voran und verbraucht die Zeichenfolge.

Zu Ihrer Information, wenn Sie Javas matches()Methode verwenden, brauchen Sie das ^und das Finale nicht wirklich $, aber sie schaden nicht. Das $Innere des Lookaheads ist jedoch erforderlich.

Alan Moore
quelle
2
Der hilfreichste Teil dieser Antwort ist, dass Sie .*am Ende Ihrer Regex hinzufügen müssen, da sonst jede Zeichenfolge abgelehnt wird.
Rav
2
Das $ Innere des negativen Lookaheads UND das .*am Ende sind beide kritische Bits. Wie immer bei REs ist eine Reihe von Unit-Tests absolut entscheidend, um die richtigen Ergebnisse zu erzielen. Diese Antwort ist 100% richtig.
Tom Dibble
1
\b(?=\w)(?!(ma|(t){1}))\b(\w*)

Dies gilt für den angegebenen regulären Ausdruck.
Das \ b soll die Wortgrenze finden.
Der positive Blick nach vorne (? = \ w) ist hier, um Leerzeichen zu vermeiden.
Der negative Blick nach vorne auf den ursprünglichen regulären Ausdruck besteht darin, Übereinstimmungen zu verhindern.
und schließlich soll (\ w *) alle verbleibenden Wörter erfassen.
Die Gruppe, die die Wörter enthält, ist Gruppe 3.
Das einfache (?! Muster) funktioniert nicht, da eine Unterzeichenfolge mit
dem einfachen ^ (?! (?: m {2} | t) $) übereinstimmt . * $ wird funktioniert nicht, da die Granularität volle Linien sind

Ofer Skulsky
quelle