49 votes

Vim Regex: Comment rechercher A AND B NOT C

J'ai beaucoup de lignes contenant les noms des Présidents des états-unis Carter, Bush, Clinton, Obama. Certains contiennent de 1 de ces noms, 2, 3, certains tous les 4 d'entre eux (dans n'importe quel ordre).

Je sais comment rechercher Carter ET Clinton ET Obama ->

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

Je sais comment rechercher Carter ET (Clinton OU Bush) ->

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

(Il y a certainement de meilleures façons de le faire)

Mais je ne peux pas comprendre comment la recherche (et j'ai regardé les questions connexes), par exemple, pour Bush ET Clinton N'Carter et encore moins la façon de rechercher, par exemple, pour Bush ET Clinton N' (Carter OU Obama).

52voto

Piet Delport Points 4649

Pour représenter un PAS, utilisez le négatif de l'assertion \@!.

Par exemple, "PAS de Bush" serait:

^\(.*Bush\)\@!

ou à l'aide de \v:

\v^(.*Bush)@!

Important: remarque le premier ^. Alors qu'il est en option si vous utilisez uniquement des affirmations positives (un match est aussi bonne que les autres), il est nécessaire d'ancrer les assertions négatives (sinon, ils peuvent toujours correspondre à la fin d'une ligne).

La traduction de "Bush ET Clinton, ET PAS (Carter OU Obama)":

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

Addendum

Pour expliquer la relation entre \& et \@=:

One&Two&Three

est interchangeable avec:

(One)@=(Two)@=Three

La seule différence est qu' \& directement miroirs \| (qui doit être plus évident et naturel), tandis que l' \@= miroirs de Perl (?=pattern).

14voto

ZyX Points 26516

Si vous souhaitez utiliser Perl-style expressions régulières après vim, oublier \&: c'est un vim-spécifique qui est inutile, puisque vim a également lookaheads, de sorte que tout r1\&r2 peut être réécrite comme \%(r1\)\@=r2. Mais lookaheads sont mieux car il y a une version négative de celui-ci et ils sont également disponibles dans la plupart de Perl-style moteurs d'expressions régulières. Votre (Bush AND Clinton AND NOT (Carter OR Obama)) peut être exprimé de la façon suivante:

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

Ou, avec de très magique:

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

Voir :h /\@=

Sujet logique interne: look-ahead " est, comme les branches: pour les regex (reg1)@=reg2 en supposant qu' reg2 correspond à la position N (match commence à la position N), moteur de regex vérifie si reg1 correspond également à cette position. Si elle ne le fait pas, alors la position est jeté et moteur d'expressions régulières tente le prochain match pour reg2. De même pour le négatif "look-ahead", mais avec la différence que le moteur d'expressions régulières les rejets à la position reg1 ne correspondent.


Exemple:

Regex: (.b)@!a.

Chaîne de caractères: aba.

  1. Trouvé match: a correspond à la position 0 (a). Essayer de faire correspondre look-ahead: ba correspond . (a) et a correspond ba (b), regarde en avant les matches, en écartant de la position.
  2. Position 1 (b) ne correspond pas à a.
  3. Trouvé match: b correspond à la position 2 (a). Essayer de faire correspondre look-ahead: a correspond b (a), mais a ne correspond pas: pas de symboles de gauche, "look-ahead" échoue. Résultat: l'expression rationnelle correspond à la position 2.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X