Ich weiß, dass es möglich ist, ein Wort zu finden und die Übereinstimmungen dann mit anderen Werkzeugen (z grep -v
. B. ) umzukehren . Ist es jedoch möglich, Zeilen, die kein bestimmtes Wort enthalten hede
, mit einem regulären Ausdruck abzugleichen?
Eingang:
hoho
hihi
haha
hede
Code:
grep "<Regex for 'doesn't contain hede'>" input
Gewünschte Ausgabe:
hoho
hihi
haha
regex
regex-negation
Knaser
quelle
quelle
([^h]*(h([^e]|$)|he([^d]|$)|hed([^e]|$)))*
? Die Idee ist einfach. Passen Sie weiter an, bis Sie den Anfang der unerwünschten Zeichenfolge sehen, und stimmen Sie dann nur in den N-1-Fällen überein, in denen die Zeichenfolge nicht fertig ist (wobei N die Länge der Zeichenfolge ist). Diese N-1-Fälle sind "h gefolgt von Nicht-e", "Er gefolgt von Nicht-d" und "Hed gefolgt von Nicht-e". Wenn Sie es geschafft haben, diese N-1-Fälle zu bestehen, haben Sie die unerwünschte Zeichenfolge nicht erfolgreich gefunden, sodass Sie[^h]*
erneut nach ihr suchen können^([^h]*(h([^e]|$)|he([^d]|$)|hed([^e]|$))?)*$
wollten die innere Gruppe optional machen und das Muster ist verankert: Dies schlägt fehl, wenn Instanzen von "hede" Teilinstanzen von "hede" vorausgehen, wie in "hhede".Antworten:
Die Vorstellung, dass Regex keine inverse Übereinstimmung unterstützt, ist nicht ganz richtig. Sie können dieses Verhalten nachahmen, indem Sie negative Umschauen verwenden:
Der obige reguläre Ausdruck stimmt mit jeder Zeichenfolge oder Zeile ohne Zeilenumbruch überein, die nicht die (Unter-) Zeichenfolge 'hede' enthält. Wie bereits erwähnt, ist dies nicht etwas, was Regex "gut" kann (oder tun sollte), aber es ist dennoch möglich.
Wenn Sie auch Zeilenumbruchzeichen verwenden müssen, verwenden Sie den Modifikator DOT-ALL (der folgende
s
im folgenden Muster):oder verwenden Sie es inline:
(wo
/.../
sind die Regex-Begrenzer, dh nicht Teil des Musters)Wenn der Modifikator DOT-ALL nicht verfügbar ist, können Sie dasselbe Verhalten mit der Zeichenklasse nachahmen
[\s\S]
:Erläuterung
Eine Zeichenfolge ist nur eine Liste von
n
Zeichen. Vor und nach jedem Zeichen steht eine leere Zeichenfolge. Eine Liste vonn
Zeichen enthält alson+1
leere Zeichenfolgen. Betrachten Sie die Zeichenfolge"ABhedeCD"
:wo die
e
's sind die leeren Zeichenfolgen. Die Regex(?!hede).
schaut nach vorne, um zu sehen, ob kein Teilstring"hede"
zu sehen ist. Wenn dies der Fall ist (also etwas anderes zu sehen ist), stimmt der.
(Punkt) mit jedem Zeichen außer einem Zeilenumbruch überein. Look-arounds werden auch als Zusicherungen mit der Breite Null bezeichnet, da sie keine Zeichen verbrauchen . Sie behaupten / validieren nur etwas.In meinem Beispiel wird also jede leere Zeichenfolge zuerst überprüft, um festzustellen, ob kein
"hede"
Zeichen vor Ihnen liegt, bevor ein Zeichen vom.
(Punkt) verbraucht wird . Der Regex(?!hede).
macht das nur einmal, also wird er in eine Gruppe eingeschlossen und null oder mehrmals wiederholt :((?!hede).)*
. Schließlich werden der Anfang und das Ende der Eingabe verankert, um sicherzustellen, dass die gesamte Eingabe verbraucht wird:^((?!hede).)*$
Wie Sie sehen können, schlägt die Eingabe
"ABhedeCD"
fehl, dae3
der reguläre Ausdruck(?!hede)
einfällt (es liegt"hede"
vor Ihnen !).quelle
grep
im OP erwähnt) mit Regex-Unterstützung verfügen alle über Funktionen, die sie theoretisch nicht regulär machen.^\(\(hede\)\@!.\)*$
Beachten Sie, dass die Lösung für nicht mit "hede" beginnt :
ist in der Regel wesentlich effizienter als die Lösung nicht enthalten „Hede“ :
Ersteres sucht nur an der ersten Position der Eingabezeichenfolge und nicht an jeder Position nach „hede“.
quelle
(.*)(?<!hede)$
. Die Version von @Nyerguds würde ebenfalls funktionieren, verfehlt jedoch den in der Antwort erwähnten Leistungspunkt völlig.^((?!hede).)*$
? Ist es nicht effizienter zu bedienen^(?!.*hede).*$
? Es macht das gleiche, aber in weniger SchrittenWenn Sie es nur für grep verwenden, können Sie
grep -v hede
alle Zeilen abrufen, die kein Hede enthalten.ETA Oh, die Frage noch einmal zu lesen,
grep -v
ist wahrscheinlich das, was Sie unter "Werkzeugoptionen" verstanden haben.quelle
grep -v -e hede -e hihi -e ...
grep -v "hede\|hihi"
:)grep -vf pattern_file file
egrep
odergrep -Ev "hede|hihi|etc"
um das unangenehme Entkommen zu vermeiden.Antworten:
Erläuterung:
^
(
Am Anfang der Zeichenfolge, Gruppierung und Erfassung auf \ 1 (0 oder mehr Mal (entspricht der größtmöglichen Menge)),(?!
schauen Sie nach vorne , um festzustellen, ob dies nicht der Fall ist.hede
deine Saite,)
Ende der Vorausschau,.
jedes Zeichen außer \ n,)*
Ende von \ 1 (Hinweis: Da Sie für diese Erfassung einen Quantifizierer verwenden, wird nur die LETZTE Wiederholung des erfassten Musters in \ 1 gespeichert)$
vor einem optionalen \ n, und das Ende der Zeichenfolgequelle
^((?!DSAU_PW8882WEB2|DSAU_PW8884WEB2|DSAU_PW8884WEB).)*$
Die gegebenen Antworten sind vollkommen in Ordnung, nur ein akademischer Punkt:
Reguläre Ausdrücke im Sinne der theoretischen Informatik sind nicht in der Lage, dies so zu tun. Für sie musste es ungefähr so aussehen:
Dies entspricht nur einer vollständigen Übereinstimmung. Es wäre noch umständlicher, dies für Teilspiele zu tun.
quelle
(hede|Hihi)
" zu sagen ? (Dies ist vielleicht eine Frage an CS.)Wenn der Regex-Test nur fehlschlagen soll, wenn die gesamte Zeichenfolge übereinstimmt, funktioniert Folgendes:
Beispiel: Wenn Sie alle Werte außer "foo" zulassen möchten (dh "foofoo", "barfoo" und "foobar" werden bestanden, "foo" jedoch fehlschlägt), verwenden Sie:
^(?!foo$).*
Wenn Sie auf exakte Gleichheit prüfen , besteht eine bessere allgemeine Lösung in diesem Fall natürlich darin, die Gleichheit der Zeichenfolgen zu überprüfen, d. H.
Sie können die Negation sogar außerhalb des Tests platzieren, wenn Sie Regex-Funktionen benötigen (hier Groß- und Kleinschreibung und Bereichsanpassung):
Die Regex-Lösung oben in dieser Antwort kann jedoch in Situationen hilfreich sein, in denen ein positiver Regex-Test erforderlich ist (möglicherweise von einer API).
quelle
" hede "
?\s
Direktive entspricht einem einzelnen Leerzeichen^(?!\s*hede\s*$).*
FWIW, da reguläre Sprachen (auch als rationale Sprachen bezeichnet) unter Ergänzung geschlossen werden, ist es immer möglich, einen regulären Ausdruck (auch als rationaler Ausdruck bezeichnet) zu finden, der einen anderen Ausdruck negiert. Dies wird jedoch nicht von vielen Tools implementiert.
Vcsn unterstützt diesen Operator (den er
{c}
als Postfix bezeichnet).Sie definieren zunächst die Art Ihrer Ausdrücke: Etiketten Buchstaben sind (
lal_char
) zur Auswahl ,a
umz
zum Beispiel (Definition des Alphabets , wenn sie mit Komplementierung funktioniert, natürlich sehr wichtig), und der „Wert“ für jedes Wort berechnet ist nur ein Boolean :true
das Wort wird akzeptiertfalse
, abgelehnt.In Python:
dann geben Sie Ihren Ausdruck ein:
Konvertieren Sie diesen Ausdruck in einen Automaten:
Konvertieren Sie diesen Automaten schließlich wieder in einen einfachen Ausdruck.
wo
+
wird normalerweise bezeichnet|
,\e
bezeichnet das leere Wort und[^]
wird normalerweise geschrieben.
(ein beliebiges Zeichen). Also mit ein bisschen Umschreiben()|h(ed?)?|([^h]|h([^e]|e([^d]|d([^e]|e.)))).*
.Sie können dieses Beispiel sehen hier , und versuchen VCSN Online gibt .
quelle
|
nicht gut gespielt.'^(()|h(ed?)?|([^h]|h([^e]|e([^d]|d([^e]|e.)))).*)$'
.Hier ist eine gute Erklärung, warum es nicht einfach ist, einen beliebigen regulären Ausdruck zu negieren. Ich muss jedoch den anderen Antworten zustimmen: Wenn dies etwas anderes als eine hypothetische Frage ist, dann ist eine Regex hier nicht die richtige Wahl.
quelle
Bei negativem Lookahead kann der reguläre Ausdruck mit etwas übereinstimmen, das kein bestimmtes Muster enthält. Dies wird von Bart Kiers beantwortet und erklärt. Tolle Erklärung!
Mit der Antwort von Bart Kiers testet der Lookahead-Teil jedoch 1 bis 4 Zeichen voraus, während er mit einem einzelnen Zeichen übereinstimmt. Wir können dies vermeiden und den Lookahead-Teil den gesamten Text überprüfen lassen, sicherstellen, dass kein "Hede" vorhanden ist, und dann kann der normale Teil (. *) Den gesamten Text auf einmal essen.
Hier ist der verbesserte reguläre Ausdruck:
Beachten Sie, dass der (*?) Lazy Quantifier im negativen Lookahead-Teil optional ist. Sie können stattdessen (*) Greedy Quantifier verwenden, abhängig von Ihren Daten: Wenn 'hede' vorhanden ist und in der ersten Hälfte des Textes, kann der Lazy Quantifier sei schneller; Andernfalls ist der gierige Quantifizierer schneller. Wenn 'hede' jedoch nicht vorhanden ist, wären beide gleich langsam.
Hier ist der Demo-Code .
Weitere Informationen zu Lookahead finden Sie in dem großartigen Artikel: Mastering Lookahead und Lookbehind .
Schauen Sie sich auch RegexGen.js an , einen JavaScript-Generator für reguläre Ausdrücke, mit dem Sie komplexe reguläre Ausdrücke erstellen können. Mit RegexGen.js können Sie den Regex besser lesbar erstellen:
quelle
^(?!.*(str1|str2)).*$
^(?!.*?(?:str1|str2)).*$
abhängig von Ihren Daten. Das wurde hinzugefügt,?:
da wir es nicht erfassen müssen.Benchmarks
Ich habe mich entschlossen, einige der vorgestellten Optionen zu bewerten, ihre Leistung zu vergleichen und einige neue Funktionen zu verwenden. Benchmarking für .NET Regex Engine: http://regexhero.net/tester/
Benchmark-Text:
Die ersten 7 Zeilen sollten nicht übereinstimmen, da sie den gesuchten Ausdruck enthalten, während die unteren 7 Zeilen übereinstimmen sollten!
Ergebnisse:
Ergebnisse sind Iterationen pro Sekunde als Median von 3 Läufen - Größere Anzahl = Besser
Da .NET keine Aktionsverben (* FAIL usw.) unterstützt, konnte ich die Lösungen P1 und P2 nicht testen.
Zusammenfassung:
Ich habe versucht, die meisten vorgeschlagenen Lösungen zu testen. Einige Optimierungen sind für bestimmte Wörter möglich. Wenn beispielsweise die ersten beiden Buchstaben der Suchzeichenfolge nicht identisch sind, kann Antwort 03 erweitert werden, um
^(?>[^R]+|R+(?!egex Hero))*$
einen kleinen Leistungsgewinn zu erzielen.Die insgesamt am besten lesbare und leistungsmäßig schnellste Lösung scheint jedoch 05 zu sein, wenn eine bedingte Anweisung verwendet wird, oder 04 mit dem Possessivquantifizierer. Ich denke, die Perl-Lösungen sollten noch schneller und leichter lesbar sein.
quelle
^(?!.*hede)
. /// Außerdem ist es wahrscheinlich besser, die Ausdrücke für den übereinstimmenden Korpus und den nicht übereinstimmenden Korpus getrennt zu ordnen, da dies normalerweise der Fall ist, wenn die meisten Zeilen übereinstimmen oder die meisten Zeilen nicht.Kein regulärer Ausdruck, aber ich fand es logisch und nützlich, serielle Greps mit Pipe zu verwenden, um Rauschen zu vermeiden.
z.B. Durchsuchen Sie eine Apache-Konfigurationsdatei ohne alle Kommentare.
und
Die Logik von seriellen Greps ist (kein Kommentar) und (entspricht dir)
quelle
grep -v
good_stuff #comment_stuff
Damit vermeiden Sie es, an jeder Position einen Lookahead zu testen:
äquivalent zu (für .net):
Alte Antwort:
quelle
/^[^h]*(?:h+(?!ede)[^h]*)*$/
Das oben Genannte
(?:(?!hede).)*
ist großartig, weil es verankert werden kann.In diesem Fall würde jedoch Folgendes ausreichen:
Diese Vereinfachung kann mit "UND" -Klauseln versehen werden:
quelle
So würde ich es machen:
Genau und effizienter als die anderen Antworten. Es implementiert Friedls Effizienztechnik "Unrolling-the-Loop" und erfordert viel weniger Backtracking.
quelle
Wenn Sie ein Zeichen abgleichen möchten, um ein Wort zu negieren, das der Zeichenklasse ähnelt:
Zum Beispiel eine Zeichenfolge:
Verwende nicht:
Verwenden:
Hinweis
"(?!bbb)."
ist weder Lookbehind noch Lookahead, es ist Lookcurrent, zum Beispiel:quelle
(?!
). Positive Vorschau des Präfix wäre ,(?=
während die entsprechenden Präfixe Lookbehind sein würden(?<!
und(?<=
jeweils. Ein Lookahead bedeutet, dass Sie die nächsten Zeichen (also „voraus“) lesen, ohne sie zu verbrauchen. Ein Lookbehind bedeutet, dass Sie Zeichen überprüfen, die bereits verbraucht wurden.Eine meiner Meinung nach besser lesbare Variante der Top-Antwort:
Grundsätzlich gilt: "Nur dann am Anfang der Zeile übereinstimmen, wenn sie kein" Hede "enthält" - die Anforderung wurde also fast direkt in Regex übersetzt.
Natürlich können mehrere Fehleranforderungen gestellt werden:
Einzelheiten: Der ^ -Anker stellt sicher, dass die Regex-Engine die Übereinstimmung nicht an jeder Stelle in der Zeichenfolge wiederholt, die mit jeder Zeichenfolge übereinstimmen würde.
Der ^ Anker am Anfang soll den Anfang der Linie darstellen. Das grep-Tool stimmt mit jeder Zeile einzeln überein. In Kontexten, in denen Sie mit einer mehrzeiligen Zeichenfolge arbeiten, können Sie das Flag "m" verwenden:
oder
quelle
Das OP hat weder angegeben noch Tagden Beitrag angegeben, in welchem Kontext (Programmiersprache, Editor, Tool) der Regex verwendet wird.
Für mich muss ich dies manchmal tun, während ich eine Datei mit bearbeite
Textpad
.Textpad
unterstützt einige Regex, unterstützt jedoch weder Lookahead noch Lookbehind, sodass einige Schritte erforderlich sind.Wenn ich alle Zeilen beibehalten möchte, die die Zeichenfolge NICHT enthalten
hede
, würde ich dies folgendermaßen tun:Jetzt haben Sie den Originaltext mit allen Zeilen, die die Zeichenfolge enthalten,
hede
entfernt.Wenn ich etwas anderes tun möchte, um nur Zeilen zu verwenden, die die Zeichenfolge NICHT enthalten
hede
, würde ich dies folgendermaßen tun:quelle
Da hat sonst niemand eine direkte Antwort auf die gestellte Frage gegeben , werde ich es tun.
Die Antwort ist, dass es mit POSIX
grep
unmöglich ist, diese Anfrage buchstäblich zu erfüllen:Der Grund dafür ist, dass POSIX
grep
nur für die Arbeit mit regulären Basisausdrücken erforderlich ist , die dieser Aufgabe einfach nicht leistungsfähig genug sind (sie können reguläre Sprachen nicht analysieren, da es an Abwechslung und Klammern mangelt).GNU
grep
implementiert jedoch Erweiterungen, die dies ermöglichen. Insbesondere\|
ist der Wechseloperator in der Implementierung von BREs durch GNU und\(
und\)
sind die Klammern. Wenn Ihre Engine für reguläre Ausdrücke Alternation, negative Klammerausdrücke, Klammern und den Kleene-Stern unterstützt und in der Lage ist, am Anfang und Ende der Zeichenfolge zu verankern, ist dies alles, was Sie für diesen Ansatz benötigen. Beachten Sie jedoch, dass negative Mengen[^ ... ]
zusätzlich zu diesen sehr praktisch sind, da Sie sie ansonsten durch einen Ausdruck der Form ersetzen müssen(a|b|c| ... )
, in der alle Zeichen aufgelistet sind, die nicht in der Menge enthalten sind. Dies ist äußerst mühsam und zu lang, umso mehr, wenn Der gesamte Zeichensatz ist Unicode.Mit GNU
grep
wäre die Antwort ungefähr so:(gefunden mit Grail und einigen weiteren Optimierungen von Hand).
Sie können auch ein Tool verwenden, das erweiterte reguläre Ausdrücke implementiert , z. B.
egrep
um die Backslashes zu entfernen:Hier ist ein Skript zum Testen (beachten Sie, dass es eine Datei
testinput.txt
im aktuellen Verzeichnis generiert ):In meinem System wird gedruckt:
wie erwartet.
Für diejenigen, die an den Details interessiert sind, besteht die angewandte Technik darin, den regulären Ausdruck, der dem Wort entspricht, in einen endlichen Automaten umzuwandeln, dann den Automaten umzukehren, indem jeder Akzeptanzzustand in Nichtakzeptanz geändert wird und umgekehrt, und dann die resultierende FA zurück in umzuwandeln ein regulärer Ausdruck.
Wie alle bemerkt haben, vereinfacht dies die Aufgabe erheblich, wenn Ihre Engine für reguläre Ausdrücke einen negativen Lookahead unterstützt. Zum Beispiel mit GNU grep:
Update: Ich habe kürzlich Kendall Hopkins 'exzellente FormalTheory- Bibliothek gefunden, die in PHP geschrieben wurde und eine ähnliche Funktionalität wie Grail bietet. Mit diesem und einem von mir selbst geschriebenen Vereinfacher konnte ich einen Online-Generator für negative reguläre Ausdrücke mit einer Eingabephrase schreiben (derzeit werden nur alphanumerische Zeichen und Leerzeichen unterstützt): http://www.formauri.es/personal/ pgimeno / misc / non-match-regex /
Dafür
hede
gibt es aus:das ist äquivalent zu den oben genannten.
quelle
Seit der Einführung von ruby-2.4.1 können wir den neuen Abwesenden Operator in Rubys regulären Ausdrücken verwenden
aus dem offiziellen doc
Somit
^(?~hede)$
erledigt in Ihrem Fall die Arbeit für Siequelle
Durch PCRE Verb
(*SKIP)(*F)
Dies würde die Zeile, die die genaue Zeichenfolge enthält
hede
und mit allen verbleibenden Zeilen übereinstimmt, vollständig überspringen .DEMO
Ausführung der Teile:
Betrachten wir den obigen regulären Ausdruck, indem wir ihn in zwei Teile aufteilen.
Teil vor dem
|
Symbol. Teil sollte nicht übereinstimmen .Teil nach dem
|
Symbol. Teil sollte abgestimmt sein .TEIL 1
Die Regex-Engine startet ihre Ausführung ab dem ersten Teil.
Erläuterung:
^
Behauptet, dass wir am Anfang sind.hede
Entspricht der Zeichenfolgehede
$
Behauptet, dass wir am Zeilenende sind.Die Zeile, die die Zeichenfolge enthält,
hede
würde also übereinstimmen. Sobald die Regex-Engine das folgende Verb(*SKIP)(*F)
( Hinweis: Sie könnten(*F)
als schreiben(*FAIL)
) sieht , überspringt sie und lässt die Übereinstimmung fehlschlagen.|
Der so genannte Änderungs- oder logische ODER-Operator, der neben dem PCRE-Verb hinzugefügt wird und mit allen Grenzen übereinstimmt, besteht zwischen jedem einzelnen Zeichen in allen Zeilen, mit Ausnahme der Zeile, die die genaue Zeichenfolge enthälthede
. Sehen Sie die Demo hier . Das heißt, es wird versucht, die Zeichen aus der verbleibenden Zeichenfolge abzugleichen. Nun würde der reguläre Ausdruck im zweiten Teil ausgeführt.TEIL 2
Erläuterung:
^
Behauptet, dass wir am Anfang sind. Das heißt, es stimmt mit allen Zeilenstarts überein, mit Ausnahme desjenigen in derhede
Zeile. Sehen Sie die Demo hier ..*
Im.
mehrzeiligen Modus würde jedes Zeichen außer Zeilenumbruch- oder Wagenrücklaufzeichen übereinstimmen. Und*
würde das vorherige Zeichen null oder mehrmals wiederholen. Also.*
würde die ganze Linie passen. Sehen Sie die Demo hier .Hey, warum hast du hinzugefügt. * Statt. +?
Denn
.*
würde mit einer Leerzeile übereinstimmen, würde aber.+
nicht mit einer Leerzeile übereinstimmen. Wir möchten alle Zeilen abgleichenhede
, außer dass möglicherweise auch in der Eingabe Leerzeilen vorhanden sind. also musst du.*
statt verwenden.+
..+
würde das vorherige Zeichen ein oder mehrere Male wiederholen. Siehe.*
Übereinstimmungen mit einer leeren Zeile hier .$
Ein Anker am Ende der Linie ist hier nicht erforderlich.quelle
Es kann für zwei reguläre Ausdrücke in Ihrem Code besser wartbar sein, eine für die erste Übereinstimmung, und wenn sie übereinstimmt, führen Sie die zweite reguläre Aussprache aus, um nach Ausreißerfällen zu suchen, die Sie beispielsweise blockieren möchten,
^.*(hede).*
und haben Sie dann die entsprechende Logik in Ihrem Code.OK, ich gebe zu, dass dies keine wirkliche Antwort auf die gestellte Frage ist und möglicherweise auch etwas mehr Verarbeitung als eine einzelne Regex benötigt. Aber für Entwickler, die hierher gekommen sind, um eine schnelle Notfalllösung für einen Ausreißerfall zu finden, sollte diese Lösung nicht übersehen werden.
quelle
Das TXR-Sprache unterstützt die Regex-Negation.
Ein komplizierteres Beispiel: Ordnen Sie alle Zeilen zu, die mit beginnen
a
und mit endenz
, aber den Teilstring nicht enthaltenhede
:Die Regex-Negation ist für sich genommen nicht besonders nützlich, aber wenn Sie auch eine Kreuzung haben, werden die Dinge interessant, da Sie eine vollständige Reihe von booleschen Mengenoperationen haben: Sie können "die Menge ausdrücken, die dieser entspricht, außer den Dingen, die dieser entsprechen".
quelle
Eine andere Möglichkeit ist, einen positiven Ausblick hinzuzufügen und zu prüfen, ob
hehe
sich irgendwo in der Eingabezeile befindet. Dann würden wir dies mit einem ähnlichen Ausdruck wie folgt negieren:mit Wortgrenzen.
Der Ausdruck wird im oberen rechten Bereich von regex101.com erläutert , wenn Sie ihn untersuchen / vereinfachen / ändern möchten, und in diesem Link , können Sie unter beobachten, wie er mit einigen Beispieleingaben .
RegEx Circuit
jex.im visualisiert reguläre Ausdrücke:
quelle
Mit der folgenden Funktion erhalten Sie die gewünschte Ausgabe
quelle
^ ((?! hede).) * $ ist eine elegante Lösung, außer da sie Zeichen verbraucht, können Sie sie nicht mit anderen Kriterien kombinieren. Angenommen, Sie möchten überprüfen, ob "hede" und "haha" nicht vorhanden sind. Diese Lösung würde funktionieren, da keine Zeichen verbraucht werden:
^ (?!. \ bhede \ b) (? =. \ bhaha \ b)
quelle
So verwenden Sie die Backtracking-Steuerverben von PCRE, um eine Zeile abzugleichen, die kein Wort enthält
Hier ist eine Methode, die ich noch nie gesehen habe:
Wie es funktioniert
Zunächst wird versucht, "hede" irgendwo in der Zeile zu finden. Wenn dies erfolgreich ist,
(*COMMIT)
weist es die Engine an dieser Stelle an, im Falle eines Fehlers nicht nur nicht zurückzuverfolgen, sondern in diesem Fall auch keine weitere Übereinstimmung zu versuchen. Dann versuchen wir, etwas zu finden, das möglicherweise nicht passt (in diesem Fall^
).Wenn eine Zeile kein "hede" enthält, stimmt die zweite Alternative, ein leeres Untermuster, erfolgreich mit der Betreffzeichenfolge überein.
Diese Methode ist nicht effizienter als ein negativer Lookahead, aber ich dachte, ich würde sie hier einfach aufsetzen, falls jemand sie geschickt findet und sie für andere, interessantere Anwendungen verwendet.
quelle
Eine einfachere Lösung ist die Verwendung des Not-Operators !
Ihre if- Anweisung muss mit "enthält" und nicht mit "ausschließen" übereinstimmen.
Ich glaube, die Designer von RegEx haben die Verwendung von Nicht-Operatoren erwartet.
quelle
Vielleicht finden Sie dies bei Google, wenn Sie versuchen, einen regulären Ausdruck zu schreiben, der Segmenten einer Linie (im Gegensatz zu ganzen Linien) entspricht, die dies nicht tun einen Teil enthalten. Ich habe eine Weile gebraucht, um das herauszufinden, also werde ich teilen:
Gegeben eine Zeichenfolge:
<span class="good">bar</span><span class="bad">foo</span><span class="ugly">baz</span>
Ich möchte zusammenpassen
<span>
Tags zuordnen, die den Teilstring "bad" nicht enthalten./<span(?:(?!bad).)*?>
wird passen<span class=\"good\">
und<span class=\"ugly\">
.Beachten Sie, dass es zwei Sätze (Ebenen) von Klammern gibt:
Demo in Ruby:
quelle
Mit ConyEdit können Sie die Befehlszeile verwenden
cc.gl !/hede/
, um Zeilen abzurufen , die keine Regex-Übereinstimmung enthalten, oder die Befehlszeile verwendencc.dl /hede/
, um Zeilen zu löschen, die die Regex-Übereinstimmung enthalten. Sie haben das gleiche Ergebnis.quelle
Ich wollte ein weiteres Beispiel hinzufügen, wenn Sie versuchen, eine ganze Zeile abzugleichen, die die Zeichenfolge X enthält , aber nicht auch die Zeichenfolge Y. .
Nehmen wir zum Beispiel an, wir möchten überprüfen, ob unsere URL / Zeichenfolge " Leckereien " enthält, solange sie nirgendwo " Schokolade " enthält.
Dieses Regex-Muster würde funktionieren (funktioniert auch in JavaScript)
(globale, mehrzeilige Flags im Beispiel)
Interaktives Beispiel: https://regexr.com/53gv4
Streichhölzer
(Diese URLs enthalten "Leckereien" und auch keine "Schokolade")
Stimmt nicht überein
(Diese URLs enthalten irgendwo "Schokolade" - daher stimmen sie nicht überein, obwohl sie "Leckereien" enthalten.)
quelle