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.


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.):


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.


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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.