5431 Stimmen

Regulärer Ausdruck, um eine Zeile zu finden, die kein Wort enthält

Ich weiß, dass es möglich ist, ein Wort abzugleichen und dann die Übereinstimmungen mit anderen Tools umzukehren (z. B. grep -v). Ist es jedoch möglich, Zeilen abzugleichen, die kein bestimmtes Wort enthalten, z. B. hede, unter Verwendung eines regulären Ausdrucks?

Eingabe:
hoho
hihi
haha
hede
Code:
grep "" input
Gewünschte Ausgabe:
hoho
hihi
haha

108 Stimmen

Wahrscheinlich ein paar Jahre zu spät, aber was ist falsch mit: ([^h]*(h([^e]|$)|he([^d]|$)|hed([^e]|$)))*? Die Idee ist einfach. Fahren Sie mit dem Abgleich fort, bis Sie den Beginn des unerwünschten Strings sehen, und gleichen Sie dann nur in den N-1 Fällen ab, in denen der String nicht abgeschlossen ist (wobei N die Länge des Strings ist). Diese N-1 Fälle sind "h gefolgt von nicht-e", "he gefolgt von nicht-d" und "hed gefolgt von nicht-e". Wenn es Ihnen gelungen ist, diese N-1 Fälle zu bestehen, haben Sie den unerwünschten String erfolgreich nicht abgeglichen, sodass Sie erneut mit der Suche nach [^h]* beginnen können.

441 Stimmen

@stevendesu: Versuche dies für 'ein-sehr-sehr-langes-Wort' oder noch besser einen halben Satz. Viel Spaß beim Tippen. Übrigens, es ist fast unleserlich. Weiß nicht über den Leistungseinfluss.

14 Stimmen

@PeterSchuetze: Sicher ist es nicht schön für sehr sehr lange Wörter, aber es ist eine praktikable und korrekte Lösung. Obwohl ich keine Tests zur Leistung durchgeführt habe, würde ich mir vorstellen, dass es nicht allzu langsam ist, da die meisten nachfolgenden Regeln ignoriert werden, bis Sie ein h sehen (oder den ersten Buchstaben des Wortes, Satzes usw. sehen). Und Sie könnten den Regex-String für lange Zeichenfolgen leicht mithilfe iterativer Konkatenation generieren. Wenn es funktioniert und schnell generiert werden kann, ist Lesbarkeit wichtig? Dafür sind Kommentare da.

24voto

ridgerunner Punkte 32111

So würde ich es machen:

^[^h]*(h(?!ede)[^h]*)*$

Genaue und effizienter als die anderen Antworten. Es implementiert Friedls Effizienztechnik "Schleifenausrollen" und erfordert viel weniger Backtracking.

1 Stimmen

Was passiert, wenn das Suchwort 2 oder mehr der gleichen ersten Buchstaben enthält? wie hhede oder hedhe??

22voto

Emma Punkte 26329

Eine weitere Option besteht darin, ein positives Look-Ahead hinzuzufügen und zu überprüfen, ob hede irgendwo in der Eingabezeile vorhanden ist, um dies zu verneinen, mit einem Ausdruck ähnlich wie:

^(?!(?=.*\bhede\b)).*$

mit Wortgrenzen.


Der Ausdruck wird im oberen rechten Panel von regex101.com erläutert, falls Sie ihn erkunden/vereinfachen/ändern möchten, und unter diesem Link können Sie sehen, wie er gegen einige Beispieleingaben übereinstimmen würde, wenn Sie möchten.


RegEx Circuit

jex.im visualisiert reguläre Ausdrücke:

Bildbeschreibung hier eingeben

5 Stimmen

Ich verstehe nicht, wie das "innere" positive Lookahead nützlich ist.

4 Stimmen

Es ist ein getarntes ^(?!.*\bhede\b).*$

20voto

diyism Punkte 11786

Wenn Sie ein Zeichen passend machen möchten, um ein ähnliches Wort zu negieren, ähnlich wie bei einer negierten Zeichenklasse:

Zum Beispiel, ein String:

Verwenden Sie nicht:

Verwenden Sie:

Beachten Sie, dass "(?!bbb)." weder ein Lookbehind noch ein Lookahead ist, es handelt sich um einen aktuellen Blick, zum Beispiel:

"(?=abc)abcde", "(?!abc)abcde"

4 Stimmen

Es gibt kein "lookcurrent" in Perl Regexp's. Dies ist wirklich ein negativer Ausblick (Präfix (?!). Das Präfix für positive Ausblicke wäre (?=, während die entsprechenden Präfixe für Blickführungen (? und `(?<=` wären, Entspchichtig. Ein Ausblick bedeutet, dass Sie die nächsten Zeichen lesen (deshalb „voraus“), ohne sie zu verbrauchen. Ein Rückblick bedeutet, dass Sie Zeichen überprüfen, die bereits verbraucht wurden.

1 Stimmen

Nicht sicher, wie (?!abc)abcde überhaupt Sinn ergibt.

15voto

Kevin Fegan Punkte 1252

Der OP hat den Beitrag nicht spezifiziert oder Tag um den Kontext (Programmiersprache, Editor, Tool) anzugeben, in dem das Regex verwendet werden soll.

Für mich muss ich manchmal beim Bearbeiten einer Datei mit Textpad dies tun.

Textpad unterstützt einige Regex, unterstützt jedoch kein Lookahead oder Lookbehind, daher sind mehrere Schritte erforderlich.

Wenn ich alle Zeilen behalten möchte, die nicht den Text hede enthalten, würde ich es folgendermaßen tun:

1. Durchsuchen/Ersetzen der gesamten Datei, um am Anfang jeder Zeile mit Text eine eindeutige "Tag" hinzuzufügen.

    Suchstring:^(.)  
    Ersetzungsstring:<@#-unique-#@>\1  
    Alle ersetzen  

2. Löschen aller Zeilen, die den Text hede enthalten (Ersetzungsstring ist leer):

    Suchstring:<@#-unique-#@>.*hede.*\n  
    Ersetzungsstring:  
    Alle ersetzen  

3. Zu diesem Zeitpunkt enthalten alle verbleibenden Zeilen nicht den Text hede. Entfernen Sie den eindeutigen "Tag" aus allen Zeilen (Ersetzungsstring ist leer):

    Suchstring:<@#-unique-#@>
    Ersetzungsstring:  
    Alle ersetzen  

Jetzt haben Sie den Originaltext, bei dem alle Zeilen mit dem Text hede entfernt wurden.


Wenn ich Etwas Anderes tun möchte, jedoch nur für Zeilen, die nicht den Text hede enthalten, würde ich es folgendermaßen tun:

1. Durchsuchen/Ersetzen der gesamten Datei, um am Anfang jeder Zeile mit Text eine eindeutige "Tag" hinzuzufügen.

    Suchstring:^(.)  
    Ersetzungsstring:<@#-unique-#@>\1  
    Alle ersetzen  

2. Für alle Zeilen, die den Text hede enthalten, entfernen Sie den eindeutigen "Tag":

    Suchstring:<@#-unique-#@>(.*hede)
    Ersetzungsstring:\1  
    Alle ersetzen  

3. Zu diesem Zeitpunkt enthalten alle Zeilen, die mit dem eindeutigen "Tag" beginnen, nicht den Text hede. Ich kann nun mein Etwas Anderes nur auf diese Zeilen anwenden.

4. Wenn ich fertig bin, entferne ich den eindeutigen "Tag" aus allen Zeilen (Ersetzungsstring ist leer):

    Suchstring:<@#-unique-#@>
    Ersetzungsstring:  
    Alle ersetzen

13voto

aelor Punkte 10370

Seit der Einführung von ruby-2.4.1 können wir den neuen Absent Operator in Ruby-Regular Expressions verwenden

vom offiziellen Dok

(?~abc) entspricht: "", "ab", "aab", "cccc", usw.
Es entspricht nicht: "abc", "aabc", "ccccabc", usw.

Also erledigt in Ihrem Fall ^(?~hede)$ die Arbeit für Sie

2.4.1 :016 > ["hoho", "hihi", "haha", "hede"].select{|s| /^(?~hede)$/.match(s)}
 => ["hoho", "hihi", "haha"]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X