Vim: insira os mesmos caracteres em várias linhas


306

Às vezes, quero editar um determinado bloco visual de texto em várias linhas.

Por exemplo, eu pegaria um texto assim:

name
comment
phone
email

E fazer parecer assim

vendor_name
vendor_comment
vendor_phone
vendor_email

Atualmente, o jeito que eu faria agora é ...

  1. Selecione todas as 4 linhas de um bloco pressionando Ve depois jquatro vezes.
  2. Recuar com >.
  3. Volte uma letra com h.
  4. Vá para bloquear o modo visual com Ctrlv.
  5. Selecione quatro linhas abaixo pressionando jquatro vezes. Nesse ponto, você selecionou blocos visuais 4x1 de espaço em branco (quatro linhas e uma coluna).
  6. Pressione C. Observe isso praticamente recuado à esquerda por uma coluna.
  7. Digite a " vendor_"sem a citação. Observe o espaço extra que tivemos que colocar de volta.
  8. Pressione Esc. Essa é uma das poucas vezes em que uso Escpara sair do modo de inserção.Ctrlceditaria apenas a primeira linha.
  9. Repita a etapa 1.
  10. Recuar para o outro lado com <.

Não preciso recuar se houver pelo menos uma coluna de espaço em branco antes das palavras. Eu não precisaria do espaço em branco se não tivesse que limpar o bloco visual comc .

Mas se eu tiver que limpar, existe uma maneira de fazer o que fiz acima sem criar o espaço em branco necessário com recuo?

Além disso, por que a edição de várias linhas ao mesmo tempo funciona apenas saindo do modo de inserção com Escmais de Ctrlc?


Aqui está um exemplo mais complicado:

name    = models.CharField( max_length = 135 )
comment = models.TextField( blank = True )
phone   = models.CharField( max_length = 135, blank = True )
email   = models.EmailField( blank = True )

para

name    = models.whatever.CharField( max_length = 135 )
comment = models.whatever.TextField( blank = True )
phone   = models.whatever.CharField( max_length = 135, blank = True )
email   = models.whatever.EmailField( blank = True )

Neste exemplo, eu executaria o bloco visual vertical sobre o .e, em seguida, o reinserria durante o modo de inserção, ou seja, tipo .whatever.. Espero que agora você possa ver a desvantagem deste método. Estou limitado a selecionar apenas uma coluna de texto que seja igual na posição vertical .


9
Melhor maneira: ":% s / ^ / vendor_ /"
Paul Tomblin

1
Obrigado pela resposta. Isso funciona se eu quiser apenas acrescentar uma palavra a cada linha. Mas o método que eu uso pode ser feito em qualquer posição. Deixe-me adicionar outro meu exemplo com um exemplo mais complicado.
precisa saber é o seguinte

3
Em seguida, realce as linhas que pretende alterar com shift-V, e digite uma pesquisa apropriada e comando replace - no segundo exemplo,:s/models\./\0whatever./
Paul Tomblin

Muitas maneiras de conseguir o que foi dito acima. Para responder completamente a todas as partes da pergunta e parte 1), regex ou modo visual, edito esc funciona muito bem como oferecido nas respostas (prefiro a seleção visual no GVIM). Para a parte 2), talvez a macro seja mais fácil, como oferecido por Brian Neal. O melhor recurso que conheço para todos esses tipos de "como fazer" é o Practical Vim, de Drew Neil. Excelente leitura rápida e referência leve sempre que você esquecer uma fórmula. Espero que esta recomendação ajude alguém, valerá a pena o esforço para muitos usuários do vim.
Arcseldon

@ Paul: E se você estiver contando as teclas digitadas , poderá substituir \0por &.
Icktoofay 8/08

Respostas:


912
  1. Mova o cursor para ndentro name.
  2. Entre no modo de bloqueio visual ( Ctrlv).
  3. Pressione jtrês vezes (ou 3j).
  4. Pressione I(capital i).
  5. Digite vendor_. Nota: Ele somente atualizará a tela na primeira linha - até que Escseja pressionado (6.), quando todas as linhas serão atualizadas.
  6. Pressione Esc.

mini-screencast demonstrando o método

Uma maiúscula Ideve ser usada em vez de minúscula i, porque a minúscula ié interpretada como o início de um objeto de texto , o que é bastante útil por si só, por exemplo, para selecionar dentro de um bloco de tag ( it):

mini-screencast mostrando a utilidade do objeto de texto 'it'


12
Não consegui fazer isso funcionar no Windows (já que o CTRL + V é mapeado para colar na área de transferência). Mas o Vim também mapeou isso para Ctrl + Q para a versão do Windows.
Arnestig

2
@ Ven: O Vim não está realmente ocupado durante esse período - está apenas esperando você pressionar outra tecla e, eventualmente, atingir o tempo limite. Duas experiências para você: primeiro, tente pressionar escape e imediatamente pressione outra tecla, como jou ^L. Você deve ver que o Vim não estava ocupado, afinal; estava apenas esperando. Segundo, tente alterar 'timeout'para um valor mais baixo, como 80(em vez do padrão 1000) e observe que o tempo limite é atingido mais rapidamente.
Icktoofay 8/08

1
@icktoofay Parece que a variável que você deseja definir timeoutlennão é timeout.
Jez

4
@ANjaNA: Se o local onde você deseja inserir estiver todos na mesma coluna (por exemplo, se os números tiverem o mesmo comprimento), você poderá usar a mesma técnica, exceto pressionando em Avez de I, que será inserido depois do bloco selecionado e não antes. Se suas linhas tiverem comprimentos diferentes, isso não funcionará; Eu gosto de usar uma substituição correspondente ao final de cada linha para isso, por exemplo, selecionando algumas linhas e usando :s/$/inserted/.
icktoofay

3
Eu tive que pressionar seta para baixo depois de pressionar Esc para chegar a este trabalho
GeoSword

69

Outra abordagem é usar o comando .( dot) em combinação com I.

  1. Mova o cursor onde você deseja iniciar
  2. pressione I
  3. Digite o prefixo desejado (por exemplo, vendor_ )
  4. pressione esc.
  5. pressione j para descer uma linha
  6. Tipo . para repetir a última edição, inserindo automaticamente o prefixo novamente
  7. Alterne rapidamente entre je.

Acho que essa técnica geralmente é mais rápida do que o modo de bloqueio visual para pequenos números de adições e tem o benefício adicional de que, se você não precisar inserir o texto em todas as linhas de um intervalo, poderá ignorá-las facilmente pressionando j s' .

Observe que, para um grande número de adições contíguas, a abordagem ou macro de blocos provavelmente será superior.


É bom ver outra abordagem.
Ibn Saeed

Eu prefiro isso por apenas algumas linhas. Muito mais fácil de executar IMO.
precisa

Depois de digitar o prefixo desejado, você não precisa pressionar a tecla Escape?
Iamnotsam

41
  1. Selecione as linhas que você deseja modificar usando CtrlV.
  2. Pressione:

    • I: Insira antes de selecionar.
    • A: Acrescente após a seleção.
    • c: Substitua o que está selecionado.
  3. Digite o novo texto.

  4. Pressione Escpara aplicar as alterações a todas as linhas selecionadas.

4
Excelente! Eu apenas destacaria a etapa final Escpara os noobs do VIM como eu - levei um tempo para descobrir que as alterações são propagadas "mais tarde"!
Bugs Bunny

1
Bom, também não sabia sobre as opções "A" e "C".
hobbes3

Por que isso não funciona v? Eu posso fazer isso Ctrl+V --> A, mas fazer vpara selecionar o texto não funciona - Aapenas acrescenta a essa linha. Eles não são ambos seleção? Além disso, muito estranho - Aapenas acrescenta ao final da linha SE eu estender o bloco visual até o final da linha; caso contrário, ele será anexado onde quer que o bloco visual termine para cada linha. É como se não reconhecesse a diferença entre ae A.
Alex G

1
Eu precisava usar em cvez de C, mas funcionou perfeitamente bem. Obrigado
Tarol

29

Eu usaria uma macro para registrar minhas ações e depois a repetiria.

  1. Coloque o cursor na primeira letra do nome .
  2. Acertar qq para iniciar a gravação no buffer q.
  3. Clique ipara entrar no modo de inserção, digite vector_ e, em seguida, pressioneEsc para sair do modo de inserção.
  4. Agora bata 0 para voltar ao início da linha.
  5. Agora bata j para descer.
  6. Agora pressione qnovamente para parar a gravação.

Agora você tem uma boa macro.

Digite 3@qpara executar sua macro três vezes para fazer o restante das linhas.


"Q" é especial (para "macro rápida"?)?
Peter Mortensen

Como a macro pode se tornar persistente (trabalhando em várias sessões)?
Peter Mortensen

O @PeterMortensen Vim possui um recurso chamado sessões que persistirá em buffers (e muitas outras coisas) nas quais você pode analisar.
Brian Neal

27
:%s/^/vendor_/

Ou eu estou esquecendo de alguma coisa?


Você está perdendo o fato de que provavelmente é um subtexto em um arquivo com muitas outras linhas nas quais o vender_prefixo é indesejado.
precisa

9
@ Dan Se apenas um subtexto é necessário, você pode limitar a pesquisa a um conjunto de números de linha, por exemplo1,4s/^/vendor_/
Brad Koch

1
@BradKoch Interessante. Eu não estava ciente das restrições de número de linha, obrigado por isso.
Dan Bechard #

8
é interessante, mas o mais prático é bloquear visualmente selecionar com Ve digitar :. Ele vai prefixar a expressão ed com :'<,'>que fazem a ed aplicam-se apenas à seleção com:'<,'>s/^/vendor_/
Dolanor

12

Atualizado janeiro de 2016

Embora a resposta aceita seja uma ótima solução, na verdade, trata-se de um pouco menos de teclas digitadas e dimensiona melhor - com base em princípio na resposta aceita.

  1. Mova o cursor para ndentro name.
  2. Entre no modo de bloqueio visual ( ctrlv).
  3. pressione 3j
  4. Pressione I.
  5. Digite vendor_.
  6. Pressione esc.

ilustração visual

Observe que isso tem menos pressionamentos de tecla do que a resposta aceita fornecida (compare a Etapa 3). Contamos apenas o número de j ações a serem executadas.

Se você tiver os números de linha ativados (como ilustrado acima) e souber o número da linha para a qual deseja mover, a etapa 3 poderá ser alterada para # Gonde # é o número da linha desejada.

No nosso exemplo acima, isso seria 4G. No entanto, ao lidar com apenas alguns números de linha, uma contagem explícita funciona bem.


7

Eu queria comentar muitas linhas em algum arquivo de configuração em um servidor que só tinha vi (sem nano), então o método visual também era complicado, e aqui está como eu fiz isso.

  1. Abrir arquivo vi file
  2. Exibir números de linha :set number!ou:set number
  3. Em seguida, use os números das linhas para substituir o início da linha por "#", como?

:35,77s/^/#/

Nota: os números são inclusivos, as linhas de 35 a 77, ambas incluídas, serão modificadas.

Para remover o comentário / desfazer isso, basta usar :35,77s/^#//

Se você deseja adicionar uma palavra de texto como um comentário após cada linha de código, também pode usar:

:35,77s/$/#test/ (para idiomas como Python)

:35,77s/;$/;\/\/test/ (para idiomas como Java)

créditos / referências:

  1. /unix/84929/uncommenting-multiple-lines-of-code-specified-by-line-numbers-using-vi-or-vim

  2. /unix/120615/how-to-comment-multiple-lines-at-once


Essa foi a solução perfeita para mim, pois geralmente estou usando o vim-tiny.
JSON C11

7

Você também pode ter um caso de uso em que deseja excluir um bloco de texto e substituí-lo.

Como isso

Hello World

Hello World

Para

Hello Cool

Hello Cool

Você pode apenas bloquear visualmente selecionar "Mundo" nas duas linhas.

Tipo c para alterar - agora você estará no modo de inserção.

Insira o material que você quer e aperte escape.

Ambos são refletidos verticalmente. Funciona exatamente como 'I', exceto que substitui o bloco pelo novo texto em vez de inseri-lo.


6

Suponha que você tenha este arquivo:

something

name
comment
phone
email

something else
and more ...

Você deseja adicionar "vendor_" na frente de "nome", "comentário", "telefone" e "email", independentemente de onde eles apareçam no arquivo .

:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc

A cbandeira solicitará sua confirmação. Você pode soltar isso se não desejar o prompt.


5

Uma alternativa que pode ser mais flexível:

Exemplo: Para inserir o texto XYZ no início da linha

:%norm IXYZ

O que está acontecendo aqui?

  • % == Executar em todas as linhas
  • norm == Execute as seguintes teclas no modo normal
  • I == Inserir no início da linha
  • XYZ == O texto que você deseja inserir

Então você bate Enter, e ele executa.

Específico ao seu pedido:

:%norm Ivendor_

Você também pode escolher um intervalo específico:

:2,4norm Ivendor_

Ou execute em um intervalo visual selecionado:

:'<,'>norm Ivendor_

1
é possível enviar seqüências de teclas como <Esc> enquanto estiver no modo de inserção (norma Iabc <ESC>) para fazer coisas mais interessantes?
batbrat

1
@batbrat Acabei de descobrir isso! Você pode pressionar ctrl-v ctrl-[para inserir um "Esc escapado", que o leva de volta ao "modo normal" para o objetivo do seu comando normal. Acabei de testar isso com '<,'>norm Iaa^[ysiw", onde ^[está o Esc escapado.
Aubrey Lavigne

4
Use Ctrl+V to enter visual block mode
Move Up/Down to select the columns of text in the lines you want to comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line

esse método funciona para todas as versões do vim ou requer plugins do vim? a razão pela qual pergunto é b / c, às vezes funciona em algumas máquinas, mas às vezes não. Eu não consigo descobrir a diferença. vim que vem com o git no windows - não consigo fazê-lo funcionar. em algumas máquinas linux ubuntu e centos, não consigo fazê-lo funcionar. tive sucesso em alguns casos raros, mas não consegui reproduzir o sucesso. é um mistério. nada parece acontecer depois que eu pressione ESC.
Davidj411

estranhamente, funciona para mim agora. nada mudou, exceto talvez as estrelas :) enquanto procurava a solução para o meu problema, encontrei algo nesta página que menciona algo a ser procurado no vim vim.wikia.com/wiki/Inserting_text_in_multiple_lines No Vim, verifique se você tem o recurso blockwise-operadores (I, A e mais) digitando o comando: version. A saída deve incluir + visualextra.
Davidj411

Eu pretendia adicionar um comentário em geral, não a sua resposta. A maioria dessas respostas diz a mesma coisa, mas usando palavras diferentes. O meu tinha algo diferente a oferecer e incluía um link.
Davidj411

2
  1. Ctrl + v para ir para o modo de bloqueio visual
  2. Selecione as linhas usando as setas para cima e para baixo
  3. Digite minúsculas 3i(pressione minúsculas I três vezes)
  4. I(pressione capital I. Isso o levará ao modo de inserção.)
  5. Escreva o texto que você deseja adicionar
  6. Esc
  7. Pressione a seta para baixo
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.