Encontre e substitua strings no vim em várias linhas


352

Eu posso fazer :%s/<search_string>/<replace_string>/gsubstituindo uma string em um arquivo ou :s/<search_string>/<replace_string>/substituindo na linha atual.

Como posso selecionar e substituir palavras de linhas seletivas no vim?

Exemplo: substitua o texto das linhas 6-10, 14-18mas não de 11-13.



Respostas:


255

O :&&comando repete a última substituição com os mesmos sinalizadores. Você pode fornecer os intervalos adicionais (e concatenar quantos quiser):

:6,10s/<search_string>/<replace_string>/g | 14,18&&

Se você tiver muitos intervalos , prefiro usar um loop:

:for range in split('6,10 14,18')| exe range 's/<search_string>/<replace_string>/g' | endfor

5
Obrigado. Nota para futuros usuários - :6,10s/<search_string>/<replace_string>/g | :14,18&& | :20,23&& | :28,31&&também funcionará, o forloop facilita a lembrança e a execução.
1

5
Estou feliz por ter gostado! Os :comandos subsequentes são opcionais, btw, para que você possa salvar mais algumas teclas.
Ingo Karkat

2
:&&economizará centenas de pressionamentos de tecla por semana. Obrigado!
pdoherty926

Funciona sem o 'g' no final do meu vim. Então, talvez, quando você especificar o intervalo de linhas, ele não precisará de uma bandeira global.
Tayyar R

3
@TayyarR O intervalo abrange as linhas (verticalmente, por assim dizer), enquanto o sinalizador 'g' determina se apenas uma ou todas as correspondências dentro da linha (horizontalmente) são substituídas.
Ingo Karkat 15/02

385

Substitua tudo:

:%s/foo/bar/g

Encontre cada ocorrência de 'foo' (em todas as linhas) e substitua-a por 'bar'.

Para linhas específicas:

:6,10s/foo/bar/g

Mude cada 'foo' para 'bar' para todas as linhas da linha 6 para a linha 10 inclusive.


3
qual é o propósito de / g aqui? Desculpe, eu sou novo no Linux
Raja Anbazhagan

4
@RajaAnbazhagan A parte final desta expressão, após a última /, é onde você indica sinalizadores para a operação. Este comando normalmente substitui a primeira correspondência em uma linha; Com a gbandeira, ela substituirá todas as ocorrências.
Litty 18/09/17

17
Você realmente deve fazer referência às suas fontes (por exemplo, vim.wikia.com/wiki/Search_and_replace), se deseja copiar e colar o trabalho de outra pessoa.
Andrew S

2
A %coisa faz o trabalho! Caso contrário, é apenas a primeira ocorrência.
Santosh Kumar

7
%=> execute este comando em todas as linhas. g=> corresponde a várias ocorrências na mesma linha.
shaahiin

55

Como observação lateral, em vez de precisar digitar os números das linhas, apenas destaque as linhas nas quais deseja encontrar / substituir em um dos modos visuais:

  • VISUALmode ( V)
  • VISUAL BLOCKmodo ( Ctrl+ V)
  • VISUAL LINEmodo ( Shift+ V, funciona melhor no seu caso)

Depois de selecionar as linhas a serem substituídas, digite seu comando:

:s/<search_string>/<replace_string>/g

Você notará que o intervalo '<,'>será inserido automaticamente para você:

:'<,'>s/<search_string>/<replace_string>/g

Aqui '<significa simplesmente primeira linha destacada , e '>meios última linha destacada .

Observe que o comportamento pode ser inesperado quando está no NORMALmodo: '<e '>aponte para o início e o fim do último destaque realizado em um dos VISUALmodos. Em vez disso, no NORMALmodo, o número da linha especial .pode ser usado, o que significa simplesmente linha atual . Portanto, você pode encontrar / substituir apenas na linha atual como esta:

:.s/<search_string>/<replace_string>/g

Outra coisa a ser observada é que inserir um segundo :entre o intervalo e o comando find / replace não faz mal, ou seja, esses comandos ainda funcionarão:

:'<,'>:s/<search_string>/<replace_string>/g
:.:s/<search_string>/<replace_string>/g

11
> Exemplo: substitua o texto das linhas 6-10, 14-18, mas não das 11-13. - sua resposta não responde a essa pergunta, não é?
poige

27

Você pode fazer isso com duas seqüências de localização / substituição

  :6,10s/<search_string>/<replace_string>/g
  :14,18s/<search_string>/<replace_string>/g

A segunda vez que tudo que você precisa ajustar é o intervalo. Em vez de digitar tudo, eu lembraria do último comando e editaria apenas o intervalo


20

No vim, se você estiver confuso de que todas as linhas serão afetadas, use abaixo

 :%s/foo/bar/gc  

Mude cada 'foo' para 'bar', mas peça primeiro a confirmação. Pressione 'y' para sim e 'n' para não. Não se esqueça de salvar depois disso

:wq

11
Você pode realmente usar o csinalizador, além de especificar o intervalo, assim :6,10s/<search_string>/<replace_string>/cfunciona. csignifica confirm. Uso a cbandeira com bastante frequência para impedir a substituição acidental de palavras em que não pensei que elas existissem também.
Wolfson

16

Exemplos de Comando de Procura e Substituição do VI

Digamos que você gostaria de encontrar uma palavra chamada "foo" e substituir por "bar".

Primeira [Esc]tecla pressionada

Digite: (dois pontos) seguido por %s/foo/bar/e pressione a tecla [Enter]

:%s/foo/bar/


11
Seu :%s/<search_string>/<replace_string>/gcomando substituirá todas as ocorrências no arquivo inteiro. Não é exatamente a resposta para a pergunta, mas é útil, no entanto :) :) #
3100

@tanius Na verdade, foi a resposta mais direta ao meu problema. Você pode modificar a pergunta para "Localizar e substituir seqüências de caracteres no vim em linhas" Selecionadas ""
Omid N

9

Não precisamos nos preocupar em digitar o número da linha atual.

Se você gostaria de mudar cada foopara bara linha atual ( .) e as duas próximas linhas ( +2), basta fazer:

:.,+2s/foo/bar/g

Se você deseja confirmar antes que as alterações sejam feitas, substitua gpor gc:

:.,+2s/foo/bar/gc

Outra coisa interessante que costumo usar é :.,$s/foo/bar/gcpesquisar e substituir, começando da linha atual até o final do arquivo.
Wolfson

3

Pesquisar e substituir

:%s/search\|search2\|search3/replace/gci

g => pesquisa global

c => Peça confirmação primeiro

i => Não diferencia maiúsculas de minúsculas

Se você deseja substituição direta sem confirmação, use o comando abaixo

:%s/search/replace/g

Se você deseja confirmação para cada substituição, execute o comando abaixo

:%s/search/replace/gc

Peça a confirmação primeiro, aqui a pesquisa não diferencia maiúsculas de minúsculas.

:%s/search/replace/gci

1

A especificação do intervalo por meio da seleção visual é aceitável, mas quando houver operações muito simples em apenas algumas linhas que podem ser selecionadas por um operador, o melhor seria aplicar esses comandos como operadores.

Infelizmente, isso não pode ser feito por meio de comandos padrão do vim. Você pode fazer uma espécie de solução alternativa usando o! operador (filtro) e qualquer objeto de texto. Por exemplo, para aplicar a operação a um parágrafo, você pode:

!ip

Isso deve ser lido como "Aplique o operador! Dentro de um parágrafo". O operador de filtro inicia o modo de comando e insere automaticamente o intervalo de linhas seguido por um literal "!" que você pode excluir logo depois. Se você aplicar isso, ao seguinte parágrafo:

1
2  Repellendus qui velit vel ullam!
3  ipsam sint modi! velit ipsam sint
4  modi! Debitis dolorum distinctio
5  mollitia vel ullam! Repellendus qui
6  Debitis dolorum distinctio mollitia
7  vel ullam! ipsam
8
9  More text around here

O resultado depois de pressionar "! Ap" seria como:

:.,.+5

Enquanto o '.' (ponto) significa a linha atual, o intervalo entre a linha atual e as 5 linhas seguintes será usado para a operação. Agora você pode adicionar o comando substituto da mesma maneira que anteriormente.

A parte ruim é que isso não é mais fácil do que selecionar o texto para a última aplicação do operador. A parte boa é que isso pode repetir a inserção do intervalo para outros intervalos de texto semelhantes (neste caso, parágrafos) com tamanho bastante diferente. Ou seja, se mais tarde você quiser selecionar o parágrafo maior do intervalo, o '.' vontade para isso certo.

Além disso, se você gosta da ideia de usar objetos de texto semântico para selecionar o intervalo de operação, pode verificar meu plug-in EXtend.vim, que pode fazer o mesmo, mas de uma maneira mais fácil.


0

Para responder a esta pergunta:

:40,50s/foo/bar/g

substitua foo por barra nessas linhas entre a 40ª e a 50ª linha (inclusive), quando executar este comando, você poderá atualmente em qualquer linha.

:50,40s/foo/bar/g

também funciona, o vim solicitará que você confirme e faça a substituição como se tivesse inserido o primeiro comando.

:,50s/foo/bar/g

substitua foo por barra nessas linhas entre a linha em que você está atualmente e a 50ª linha (inclusive). (se você estiver em uma linha APÓS o 50º linha vim solicitará confirmação novamente)

Para esclarecer a diferença entre o vim e o plug-in vrapper do Eclipse:

Observe que no varpper

:,50s/foo/bar/g comando NÃO funcionará.

:50,40s/foo/bar/g funcionará sem pedir confirmação.

(Para Vrapper versão 0.74.0 ou anterior).


-5
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal

Suponha que você queira substituir o acima por outras informações.

COMMAND(:%s/\/sys\/sim\/source\/gm\/kg\/jl\/ls\/owow\/lsal/sys.pkg.mpu.umc.kdk./g)

Neste, o acima será substituído por ( sys.pkg.mpu.umc.kdk.).


Não tenho certeza se isso realmente responde à pergunta. A partir da pergunta, parece que a pessoa que está perguntando já está ciente de como usar %sa modificação de entrada, mas quer saber como fazê-la "semi-globalmente" (ou seja, sua especificação é as linhas 6-10 e 14-18, mas não nas linhas 11- 13)
Brandon Buck

11
Também o que é "COMMAND"? E você está sofrendo de síndrome do palito de dente inclinado .
Martin Tournoij 21/09

Para curar que a síndrome, você pode usar outro personagem como delimitador em vez do padrão /, por exemplo !, @, _::%s_/sys/sim/source/gm/kg/jl/ls/owow/lsal_sys.pkg.mpu.umc.kdk_g
MortezaE
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.