59 Stimmen

Vim Regex : Wie man nach A AND B NOT C sucht

Ich habe viele Zeilen mit den Namen der US-Präsidenten Carter, Bush, Clinton und Obama. Einige enthalten 1 dieser Namen, einige 2, einige 3, einige alle 4 (in beliebiger Reihenfolge).

Ich weiß, wie man nach Carter UND Clinton UND Obama sucht ->

:g/.*Carter\&.*Clinton\&.*Obama/p

Ich weiß, wie man nach Carter AND (Clinton OR Bush) sucht ->

:g/.*Carter\&\(.*Clinton\|.*Bush\)/p

(Es gibt sicherlich bessere Möglichkeiten, dies zu tun)

Aber ich kann nicht herausfinden, wie man z. B. nach Bush AND Clinton NOT Carter sucht (und ich habe mir die entsprechenden Fragen angesehen) und noch weniger, wie man z. B. nach Bush AND Clinton NOT (Carter OR Obama) sucht.

67voto

Pi Delport Punkte 9941

Um ein NOT darzustellen, verwenden Sie die negative Behauptung \@! .

Zum Beispiel wäre "NOT Bush":

^\(.*Bush\)\@!

oder mit \v :

\v^(.*Bush)@!

Wichtig: Beachten Sie die führende ^ . Während es optional ist, wenn Sie nur positive Behauptungen verwenden (eine Übereinstimmung ist so gut wie jede andere), ist es erforderlich, um negative Behauptungen zu verankern (sonst können sie immer noch am Ende einer Zeile übereinstimmen).

Übersetzt "Bush UND Clinton UND NICHT (Carter ODER Obama)":

\v^(.*Bush)&(.*Clinton)&(.*Carter|.*Obama)@!

Nachtrag

Zur Erklärung der Beziehung zwischen \& y \@= :

One&Two&Three

ist austauschbar mit:

(One)@=(Two)@=Three

Der einzige Unterschied besteht darin, dass \& spiegelt direkt \| (was offensichtlicher und natürlicher sein sollte), während \@= spiegelt Perl's (?=pattern) .

14voto

ZyX Punkte 50799

Wenn Sie reguläre Ausdrücke im Perl-Stil nach vim verwenden wollen, vergessen Sie \& : Es ist eine Vim-spezifische Funktion, die nutzlos ist, da Vim auch Lookaheads hat, so dass jede r1\&r2 kann wie folgt umgeschrieben werden \%(r1\)\@=r2 . Aber Lookaheads sind besser, da es eine negative Version davon gibt und sie auch in den meisten Suchmaschinen für reguläre Ausdrücke im Stil von Perl verfügbar sind. Ihr (Bush AND Clinton AND NOT (Carter OR Obama)) kann folgendermaßen ausgedrückt werden:

g/^\%(.*\%(Carter\|Obama\)\)\@!\%(.*Bush\)\@=.*Clinton/

Oder, mit sehr viel Magie:

g/^\v%(.*%(Carter|Obama))@!%(.*Bush)@=.*Clinton/

Siehe :h /\@=

Zur inneren Logik: Vorausschau ist wie Verzweigungen: für regex (reg1)@=reg2 unter der Annahme, dass reg2 Spiele auf Position N (Spiel beginnt an der Position N ), prüft die Regex-Engine, ob reg1 passt auch auf diese Position. Wenn dies nicht der Fall ist, wird die Position verworfen und die Regex-Engine versucht die nächste mögliche Übereinstimmung für reg2 . Dasselbe gilt für die negative Vorausschau, jedoch mit dem Unterschied, dass die Regex-Engine die Position verwirft, wenn reg1 fait übereinstimmen.


Beispiel:

Regex: (.b)@!a .

Zeichenfolge: aba .

  1. Übereinstimmung gefunden: a an der Position 0 übereinstimmt ( **a**ba ). Ich versuche, die Vorausschau zu erfüllen: . passt zu a ( **a**ba ) und b passt zu b ( a**b**a ), Vorausschauende Übereinstimmungen, Verwerfen der Position.
  2. Stellung 1 ( a**b**a ) nicht übereinstimmt a .
  3. Übereinstimmung gefunden: a stimmt an Position 2 überein ( ab**a** ). Ich versuche, die Vorausschau zu erfüllen: . passt zu a ( ab**a** ), sondern b stimmt nicht überein: keine Symbole übrig, Vorausschau schlägt fehl. Ergebnis: Regex passt an Position 2.

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