A pesquisa Vim substitui todos os arquivos na pasta atual (projeto)


37

Uma das perguntas abertas que tenho sobre o Vim é se existe uma maneira de executar uma pesquisa / substituição no projeto atual (aceite comigo se eu usar essa noção herdada de outros editores).

Por exemplo, suponha que eu queira pesquisar meus arquivos de projeto por um nome de método e renomeie todas as instâncias dessa chamada de método.

É assim que posso proceder com o Sublime.

insira a descrição da imagem aqui

Como você faria isso no Vim (possivelmente MacVim) sem depender de outros programas como ackou sed?

Respostas:


35

Existem várias maneiras de fazer isso.

Diretório atual interno

Se você deseja executar a pesquisa / substituição em uma árvore de projeto, pode usar a lista de argumentos do Vim .

Simplesmente abra o Vim e use o :argscomando para preencher a lista de argumentos. Você pode passar vários nomes de arquivos ou até globs.

Por exemplo, :args **/*.rbprocurará recursivamente no diretório atual por arquivos ruby. Observe que isso também é como abrir o Vim com vim **/*.rb. Você pode até usar o findcomando do shell para obter uma lista de todos os arquivos no diretório atual executando:

:args `find . -type f`

Você pode visualizar a lista de argumentos atual executando :argspor si só. Se você deseja adicionar ou excluir arquivos da lista, pode usar :argaddos :argdeletecomandos ou, respectivamente.

Quando estiver satisfeito com a lista, agora você poderá usar o poderoso :argdocomando do Vim, que executa um comando para todos os arquivos da lista de argumentos::argdo %s/search/replace/g

Aqui estão algumas dicas para pesquisar (com base em alguns dos comentários):

  1. Use um limite de palavras se quiser pesquisar "foo", mas não "foo_bar". Use as construções \<e \>ao redor do padrão de pesquisa da seguinte maneira::argdo %s/\<search\>/foobar/g
  2. Use um /csinalizador de pesquisa se desejar que o Vim peça confirmação antes de substituir um termo de pesquisa.
  3. Use um /esinalizador de pesquisa se desejar ignorar os erros "padrão não encontrado".
  4. Você também pode optar por salvar o arquivo depois de executar a pesquisa: :argdo %s/search/replace/g | update. Aqui, :updateé usado porque ele só salvará o arquivo se ele tiver sido alterado.

Buffers abertos

Se você já possui buffers abertos, deseja fazer a pesquisa / substituição, pode usar :bufdo, o que executa um comando para cada arquivo em sua lista de buffers ( :ls).

O comando é muito semelhante a :argdo: :bufdo %s/search/replace/g

Similar ao :argdoe :bufdo, há :windoe :tabdoque atuam em janelas e abas, respectivamente. Eles são usados ​​com menos frequência, mas ainda são úteis para saber.


4
Provavelmente, seria uma boa ideia usar a /cbandeira para confirmar substituições.
Romainl 29/03/2015

3
Eu também recomendaria o uso de limites de palavras \<e \>ao redor do searchpara evitar substituições parciais de palavras.
21815 Tommcdo

11
Outro comentário é que o diretório de trabalho do vim é por padrão onde você iniciou o vim, não o diretório do arquivo atual. Você pode definir o diretório de trabalho para o arquivo atual usando :cd %:p:h. Outras opções de diretório de trabalho estão listadas em vim.wikia.com/wiki/Set_working_directory_to_the_current_file .
Studgeek

30

Digamos que temos uma estrutura de projeto simples como esta:

insira a descrição da imagem aqui

greeting.txt parece

insira a descrição da imagem aqui

e info / age.txt parece

insira a descrição da imagem aqui

Digamos que queremos substituir todas as ocorrências de Sam por Bob. Aqui está o que faríamos:

  1. Definir diretório de trabalho

    Verifique se o diretório de trabalho atual do Vim é a raiz do projeto (não mostrará como fazer isso aqui).

  2. Encontre arquivos que contenham 'Sam'

    Use o comando vimgrep do Vim para procurar todas as ocorrências de Sam no projeto (nota: as **/*pesquisas em todos os arquivos recursivamente)

    :vimgrep /Sam/gj **/*
    

    Isso preencherá a lista de correções rápidas com todas as instâncias do Sam. Se você deseja visualizar a lista de correções rápidas, pode usar o comando Vim:copen insira a descrição da imagem aqui

  3. Substitua em todos os arquivos que contêm 'Sam'

    Agora, queremos executar o comando substituto do Vim dentro de cada arquivo na lista de correções rápidas. Podemos fazer isso usando o :cfdo {cmd}comando que executa {cmd} em cada arquivo na lista de correções rápidas. O {cmd} específico que queremos usar é substituteou sabreviado. A linha completa seria semelhante a:

    :cfdo %s/Sam/Bob/g
    

    Você pode adicionar o sinalizador c para confirmar todas as substituições, se desejar:

    :cfdo %s/Sam/Bob/gc
    
  4. Salve todos os arquivos

    :cfdo update
    

2
Eu gosto mais disso. É simples e funciona com o Ack (ou qualquer plug-in que preencha a janela do QuickFix).
Zuhaib

11
Esta é uma grande resposta
Peoplee

2
Estava ficando "sem escrita desde a última mudança", fazendo cfdo %s/Sam/Bob/g | updatefixo que para mim
Hakunin

@hakunin Eu recomendo definir a hiddenopção :set hiddense você ainda não o fez.
Niko Bellic

3

Embora não seja uma solução VIM, se você estiver usando VI / VIM, poderá achar mais fácil usar uma solução CLI. Para alterar todos os arquivos no diretório atual, use perlcomo foi criado para situações como esta:

$ perl -pi -e 's/foo/bar/g' *

Se você precisar fazer isso também em subdiretórios, costumo emparelhar perlcom find:

$ find . -name '*' -print0 | xargs -0 perl -pi -e 's/foo/bar/g'

O bom disso é que você pode refinar facilmente a lista para tipos de arquivos específicos. Por exemplo, para restringir a arquivos python:

$ perl -pi -e 's/foo/bar/g' *.py
$ find . -name '*.py' -print0 | xargs -0 perl -pi -e 's/foo/bar/g'

1

Para substituir a frase por outra, você pode usar o modo Vim Ex.

Por exemplo ( exé alias para vim -E):

$ ex -s +'bufdo!%s/foo/bar/g' -cxa *.*

Recursivamente em bash / zsh (com globstarconjunto, por exemplo shopt -s globstar):

$ ex -s +'bufdo!%s/foo/bar/g' -cxa **/*.*
$ ex -s +'n **/*.*' +'bufdo!%s/foo/bar/g' -cxa

Recursivamente (usando finde ignorando arquivos ocultos, como .gitarquivos):

$ find . -type f -not -path '*/\.*' -exec ex -s +'bufdo!%s/foo/bar/g' -cxa {} "+"

Nota: O :bufdocomando não é POSIX .

Nota: A sintaxe -not -path '*/\.*'é usada para ignorar arquivos ocultos (como .git).



0

Aqui está o comando shell usando finde exeditor (sem usar:bufdo ):

find . -name '*.rb' -exec ex +'%s/foo/bar/ge' -V1 -scwq! {} ';'

Isso editará todos os *.rbarquivos na pasta atual (recursivamente) e será substituído foopor bar.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.