La recherche est-elle possible dans le système regex de vim?

22

J'ai rencontré de nombreuses situations dans vim où il serait utile d'avoir des déclarations de contournement. J'ai essayé d'utiliser la syntaxe de recherche standard ( (?=), (?!)etc.) , mais il semble que vim ne le supporte pas. Vim a-t-il une syntaxe équivalente pour ces types d'instructions?

Arbre à feuilles persistantes
la source

Réponses:

29

Ancres "Zoom"

En plus de la réponse de @ jecxjo, il existe de nombreuses situations où vous pouvez utiliser les ancres de largeur nulle \zset \zeau lieu d'une recherche positive. Ces ancres définissent le début ( \zs) et la fin ( \ze) de la correspondance dans le motif complet.

Exemples

  • foo\zsbarcorrespondra barprécédé de foo( foone fait pas partie du match)
  • foo\zebarcorrespondra foosuivi de bar( barne fait pas partie du match)
  • myFunction(\zs.*\ze)correspondra aux paramètres dans un appel de fonction (à des fins de démonstration, je ne me concentre pas sur la correspondance cupide vs non gourmande)

Mettre à profit

Ceux-ci deviennent plus utiles lors de l'utilisation de la :substitutecommande. Par exemple, disons que je voulais remplacer les paramètres d'un appel de fonction myFunction()par foo:

:%s/myFunction(\zs.*\ze)/foo/

Cela laissera myFunction(et )intact, et vous n'avez pas à vous soucier de les capturer dans votre modèle ou les répéter dans votre remplacement .

Vous pouvez le faire en utilisant la fonction de lookaround du regex de Vim, mais c'est assez maladroit:

:%s/\(myFunction(\)\@<=.*\()\)\@=/foo/

(Je trouve que cette syntaxe me fait oublier ce que j'essayais de faire en premier lieu.)

Vous avez toujours besoin de regarder parfois

Il y a encore des situations où vous avez besoin de regarder autour. L'utilisation de \zset \zeest idéale pour les situations simples où vous avez quelque chose avant suivi d'un texte à faire correspondre suivi de quelque chose après . Mais si c'est plus complexe que cela, vous devrez probablement vous en tenir à la syntaxe de recherche plus lourde.

Fait amusant

Bien qu'ils soient considérablement plus laids, les contournements de Vim sont plus puissants que ceux de PCRE! Ils prennent en charge la recherche négative de longueur variable, ce qui signifie que vous pouvez affirmer qu'un modèle dont la longueur n'est pas prédéterminée n'est pas avant votre match.

PCRE ne prend pas en charge cela, car il est assez coûteux en termes de calcul. Ce n'est pas une préoccupation majeure dans Vim, car les cas d'utilisation les plus courants de l'expression régulière ont tendance à impliquer une recherche interactive où le temps de calcul est presque imperceptible pour l'utilisateur. Vous le remarquerez probablement s'il était utilisé pour la mise en évidence de la syntaxe.

Rubriques d'aide pertinentes

  • :help \zs
  • :help \ze
  • :help perl-patterns
tommcdo
la source
Je n'étais pas au courant des ancres de zoom. Merci de les avoir expliqués.
EvergreenTree du
14

Il semble que cela soit possible. Il existe un tableau simple pour passer de perl à vim.:h perl-patterns

9. Compare with Perl patterns               *perl-patterns*

Vim's regexes are most similar to Perl's, in terms of what you can do.  The
difference between them is mostly just notation;  here's a summary of where
they differ:

Capability                  in Vimspeak   in Perlspeak
----------------------------------------------------------------
force case insensitivity    \c            (?i)
force case sensitivity      \C            (?-i)
backref-less grouping       \%(atom\)     (?:atom)
conservative quantifiers    \{-n,m}       *?, +?, ??, {}?
0-width match               atom\@=       (?=atom)
0-width non-match           atom\@!       (?!atom)
0-width preceding match     atom\@<=      (?<=atom)
0-width preceding non-match atom\@<!      (?<!atom)
match without retry         atom\@>       (?>atom)

Ainsi, par exemple, si vous avez la chaîne one two threeet que vous ne souhaitez faire correspondre oneque si la <space>twosuit, vous pouvez utiliser

/one\(\stwo\)\@=

Ceci est similaire à la version Perl

m/one(?=\stwo)/
jecxjo
la source