É possível procurar no sistema regex do vim?

22

Eu encontrei muitas situações no vim em que seria útil ter instruções detalhadas. Eu tentei usar a sintaxe de lookaround padrão ( (?=), (?!)etc.) , mas parece que o vim não suporta isso. O vim tem uma sintaxe equivalente para esses tipos de instruções?

EvergreenTree
fonte

Respostas:

29

Âncoras "Zoom"

Além da resposta do @ jecxjo, há muitas situações em que você pode usar as âncoras de largura zero \zse \zenão a busca positiva. Essas âncoras definem o início ( \zs) e o final ( \ze) da correspondência dentro do padrão completo.

Exemplos

  • foo\zsbarcorresponderá barprecedido por foo( foonão faz parte da correspondência)
  • foo\zebarcorresponderá fooseguido por bar( barnão faz parte do jogo)
  • myFunction(\zs.*\ze)corresponderá aos parâmetros em uma chamada de função (para fins de demonstração, não estou focando na correspondência gananciosa versus não gananciosa)

Colocando em uso

Eles se tornam mais úteis ao usar o :substitutecomando Por exemplo, digamos que eu queira substituir os parâmetros em uma chamada de função myFunction()por foo:

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

Isso vai deixar myFunction(e )intacto, e você não precisa se preocupar com a captura-los em seu padrão ou repeti-las em sua substituição .

Você pode fazer isso usando o recurso de aparência regular do regex do Vim, mas é bastante desajeitado:

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

(Acho que essa sintaxe faz com que eu esqueça o que estava tentando fazer em primeiro lugar.)

Você ainda precisa olhar às vezes

Ainda existem situações em que você precisa de atenção. Usando \zse \zesão ótimos para situações simples em que você tem algo antes seguido de texto para combinar seguido por algo depois . Mas se for mais complexo que isso, você provavelmente terá que se ater à sintaxe mais pesada da aparência.

Fato engraçado

Embora sejam consideravelmente mais feias, a aparência do Vim é mais poderosa do que as do PCRE! Eles suportam lookbehind negativo de comprimento variável, o que significa que você pode afirmar que algum padrão cujo comprimento não é predeterminado não está antes da sua correspondência.

O PCRE não suporta isso, pois é bastante computacionalmente caro. Isso não é uma grande preocupação no Vim, pois os casos de uso mais comuns de regex tendem a envolver a pesquisa interativa, onde o tempo de computação é quase imperceptível para o usuário. Você provavelmente notaria se fosse usado para destacar a sintaxe.

Tópicos de ajuda relevantes

  • :help \zs
  • :help \ze
  • :help perl-patterns
tommcdo
fonte
Eu não estava ciente das âncoras de zoom. Obrigado por explicá-los.
EvergreenTree
14

Parece que isso é possível. Existe uma tabela simples para ir do perl ao 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)

Por exemplo, se você possui a string one two threee deseja corresponder oneapenas se a <space>twosegue, pode usar

/one\(\stwo\)\@=

Isso é semelhante à versão perl

m/one(?=\stwo)/
jecxjo
fonte