Vim: colando linhas linha por linha

8

Vamos supor que eu tenho um arquivo contendo:

xxx
yyy
zzz

e outro arquivo:

kkk
qqq
ppp

Eu quero obter:

xxxkkk
yyyqqq
zzzppp

Isso é possível no Vim com algum comando? (Tentei usar o VISUAL BLOCK, mas sem sucesso).

No meu caso particular, eu tenho dois arquivos grandes com muitas linhas para colar, então a resposta também pode ser um comando de shell, mas eu gostaria de saber se existe uma maneira de fazê-lo, mesmo dentro do mesmo arquivo.

Fabio F.
fonte

Respostas:

12

Na linha de comando, você pode tentar

paste -d '\0' file1 file2 > file3

Isso faz exatamente o que você deseja.

O modo Visual Block vimtambém é perfeitamente adequado para esta tarefa. Tem certeza de que fez corretamente? Você deve

  • Ir para o modo de bloqueio visual
  • Selecione o texto e pressione ypara puxar
  • Vá para o outro arquivo, no canto superior esquerdo da pasta para colar os dados (por último x) e pressione p.
Bernhard
fonte
Eu estava colando no Visual Block ... era exatamente o que eu queria fazer. Obrigado.
Fabio F.
1
Pelo menos com o GNU Coreutils, paste -d '' ...também funciona. Curiosamente, as páginas de manual e de informações do coreutils parecem não documentar '\ 0', mesmo que especificadas na especificação Unix única.
derobert
5

Você pode fazer diretamente ao editar file1. Digite :para alternar para o command modevim. Então digite:

%!paste -d '' - file2
cuonglm
fonte
3

Aqui está uma maneira de fazê-lo no mesmo arquivo usando apenas o Vim.

Envolve algum mapeamento de chave. Eu vim com isso uma vez quando queria organizar várias listas em estruturas semelhantes a tabelas em texto simples.

Isso depende da tecla } (chave direita) para pular os limites do parágrafo. (Os chavetas são espelhados, btw: { pula para a parte superior do arquivo e } para o final.)

Então ... suponha que você tenha um arquivo de dados como este (isso supõe que as linhas # estejam ativadas com : set nu ):

+---------------  
| 1 xxx    (cursor on line#1)  
| 2 yyy  
| 3 zzz  
| 4   
| 5 kkk  
| 6 qqq  
| 7 ppp  
+---------------  

É importante que a linha # 4 seja uma linha vazia (sem espaço em branco), explicarei o motivo daqui a pouco.

Execute o seguinte mapa de comando:
: mapear q mw} jdd'wpkJj

Isso vincula a tecla "q" a um programa de 12 caracteres, que detalharei abaixo.

Quando você pressiona "q", ele executa esse programa; observe que seu cursor, iniciado na linha 1, está agora na próxima linha, pronto para pressionar "q" novamente. Você deve ter notado que existe um caractere de espaço entre "xxx kkk"; se você não quiser, consulte "E o caractere de espaço extra?" abaixo, perto do fim.

+---------------
| 1 xxx kkk
| 2 yyy   (cursor on line #2)
| 3 zzz
| 4 
| 5 qqq
| 6 qqq
| ~
+---------------

Aqui está um detalhamento do mapeamento:

   :map q mw}jdd'wpkJj
   ^

Os dois pontos colocam você no modo de comando para que possamos emitir o comando "map".

   :map q mw}jdd'wpkJj
    ^^^^^

mapa q liga q com a seguinte sequência de caracteres. Observe que "q" é apenas a minha chave "mapear" usual; você pode usar outras teclas. Por padrão, q minúsculo é mapeado para iniciar a gravação de macro; uma vez que raramente (nunca?) uso esse "q" mais útil para macros de utilitário pontuais. Você também pode usar Q maiúsculo (por exemplo, mapa Q) ou uma tecla fnct ou assim por diante.

Agora, sempre que você pressionar "q" (no modo de navegação), o vim executará esta série de teclas:

   mw}jdd'wpkJj

O que, obviamente, parece totalmente sem sentido, então eu vou dividir ação por ação (com ^^ abaixo) para facilitar o acompanhamento do que está acontecendo.

mw}jdd'wpkJj
^^

O mw MARCA um local nomeado, o nome aqui é 'w'. Eu uso 'w' por padrão (penso nisso como meu local de trabalho '. Qualquer local nomeado, de az, funcionaria, desde que você seja consistente.
O' w 'aparecerá novamente em breve quando deseja retornar o cursor para esta linha.

mw}jdd'wpkJj
  ^

Aqui temos o botão direito do mouse } que pula o cursor para o próximo limite do parágrafo; em outras palavras, isso move o cursor para a próxima linha vazia, que é a linha 4 no nosso exemplo. (É por isso que a linha 4 deve ser uma linha vazia; sem espaços em branco, caso contrário } não a considerará um limite.)

mw}jdd'wpkJj
   ^

O j desce uma linha; esta é a navegação vi "hjkl" da velha escola. Você provavelmente também pode usar uma seta para baixo aqui, acho "j" um pouco mais fácil de ler e mais fácil de usar (porque as teclas de seta nem sempre estão no mesmo lugar entre as várias marcas de teclados de laptop e desktop, mas "hjkl "está garantido para estar sempre do lado direito da linha inicial de qualquer teclado QWERTY (o que ajuda na velocidade da digitação)).
De qualquer forma, neste momento, o cursor está na linha # 5.

+---------------  
| 1 xxx
| 2 yyy  
| 3 zzz  
| 4   
| 5 kkk   (cursor on line#5)
| 6 qqq  
| 7 ppp  
+---------------  

mw}jdd'wpkJj
    ^^

O dd é o comando de edição "delete line", portanto, ele exclui a linha atual, que é a linha 5, com o "kkk". A exclusão da linha também a coloca no buffer de colagem padrão, que usaremos o exploit para trazer o "kkk" de volta para onde queremos na linha # 1, ao lado de "xxx".

mw}jdd'wpkJj
      ^^

A sequência 'w (aspas simples w) pula o cursor de volta ao nosso marcador para "w", que coloca o cursor na linha # 1.

mw}jdd'wpkJj
        ^

O "p" minúsculo coloca o buffer padrão atual (com "kkk", como você se lembrará) após o cursor. Como o buffer contém o que costumava ser a linha 5, nosso arquivo se parece com isso agora:

+---------------
| 1 xxx
| 2 kkk    (cursor on line#2, after the freshly restored "kkk")
| 3 yyy
| 4 zzz
| 5 
| 6 qqq
| 7 ppp
+---------------

Observe como "kkk" se tornou a linha 2. (Não consigo ilustrar com facilidade para onde o cursor vai até lá ... deve estar realmente no início da linha 2).
Estamos perto, mas ainda não chegamos lá ...

mw}jdd'wpkJj
         ^^

O k minúsculo pula o cursor até a linha # 1 (navegação "hjkl" novamente) e o J maiúsculo une a próxima linha à linha atual, fazendo com que nosso arquivo fique assim (o cursor ainda está na linha # 1, entre x e k):

+---------------
| 1 xxx kkk    (cursor on line #1, between 'xxx' and 'kkk')
| 2 yyy
| 3 zzz
| 4 
| 5 qqq
| 6 ppp
+---------------


mw}jdd'wpkJj
           ^

O último j é a navegação "hjkl" mais uma vez, que move o cursor para baixo até a linha 2, o que é útil, porque é a próxima linha na qual queremos aplicar q .
De qualquer forma, ficará assim:

+---------------
| 1 xxx kkk
| 2 yyy       (cursor on #2)
| 3 zzz
| 4 
| 5 qqq
| 6 ppp
+---------------

Se você pressionar "q" novamente e ele será parecido com este (observe que o cursor está na linha # 3).

+---------------
| 1 xxx kkk
| 2 yyy qqq
| 3 zzz        (cursor on #3)
| 4 
| 5 ppp
+---------------

Enxágüe e repita conforme necessário. Acho isso útil para listas mais longas porque me permite (razoavelmente) criar indolor colunas.

Aqui está um exemplo mais longo. Adicionar uma linha em branco na linha 7 faz com que "ggg" seja empilhado primeiro na próxima coluna. Depois de descer para "lll", pule o cursor de volta para a linha 1 (deixada encaracolada, {, funciona bem para isso) e continue com "mmm". Se você decidir que não gosta da maneira como está organizando, mantenha pressionado u (desfazer) por um pouco e ajuste onde a linha "limite" será iniciada novamente.

Essa é uma daquelas coisas que funciona muito mais fácil do que é preciso explicar. Embora eu não ache que o usaria para juntar milhares de linhas, acho útil para dezenas e, ocasionalmente, para centenas.

+----------:---------------------------
|   before : after
+----------:---------------------------
|  1 aaa   :  1 aaa ggg mmm sss yyy
|  2 bbb   :  2 bbb hhh nnn ttt zzz
|  3 ccc   :  3 ccc iii ooo uuu
|  4 ddd   :  4 ddd jjj ppp vvv
|  5 eee   :  5 eee kkk qqq www
|  6 fff   :  6 fff lll rrr xxx
|  7       :-------------------------
|  8 ggg 
|  9 hhh 
| 10 iii 
| 11 jjj 
| 12 kkk 
| 13 lll 
| 14 mmm 
| 15 nnn 
| 16 ooo 
| 17 ppp 
| 18 qqq 
| 19 rrr 
| 20 sss 
| 21 ttt 
| 22 uuu 
| 23 vvv 
| 24 www 
| 25 xxx 
| 26 yyy 
| 27 zzz
+----------

E o personagem do espaço extra?
Parte do comportamento do comando Join é que ele coloca um espaço entre as linhas nas quais ele se une.
Se você não deseja um espaço entre "xxx kkk", pode
adicionar um comando delete (x) à string:

simple join (space char):  :map q mw}jdd'wpkJj
join + x (kills space):    :map q mw}jdd'wpkJxj
join w/comma:              :map q mw}jdd'wpkJR,^[j

O "join + x" mata o espaço usando x logo após juntar as duas linhas. x no modo Navegação exclui qualquer caractere em que o cursor esteja, que nesse caso era o caractere de espaço incorreto.

A "junção com vírgula" substitui o espaço por uma vírgula. Isso é basicamente o mesmo, mas analisaremos a última parte, que é um pouco diferente do exemplo anterior.

:map q mw}jdd'wpkJR,^[j
                  ^

O R -nos coloca em modo de edição (especificamente modo de substituição, que irá substituir os caracteres com o que digitar).

 :map q mw}jdd'wpkJR,^[j
                    ^

A , literalmente tipos uma vírgula, que é substitui o espaço de ofensa a esse ponto.

 :map q mw}jdd'wpkJR,^[j
                     ^^

E então ^ [ sinaliza um caractere Escape, que sai do modo Editar e nos coloca de volta no modo Navegação.
Agora estamos prontos para o j final nos levar para a próxima linha.

Para mapear um caractere de escape, você precisa pressionar ^ Q (windows) ou ^ V (linux e unix) e pressionar a tecla Esc (se não o fizer, o caractere Esc abortará o comando e sua esquerda se perguntará por que seu mapa possivelmente complexo definição desapareceu). Aqui está a sequência que você precisaria digitar para acessá-lo no Vim no Windows:

:map q mw}jdd'wpkJR,<Ctr-Q><Esc>j

Assim. Provavelmente existem dezenas de maneiras de fazer esse tipo de coisa no Vim.
Quando os delimitadores de "campo" são importantes, costumo colocar uma sequência única e simples no final de cada linha com pesquisa e substituição global, avançar e juntar as colunas da maneira que eu quero e depois substituir - tudo para obter os separadores específicos que eu quero .

Enfim, este é apenas um exemplo. Espero que você tenha achado interessante.

netdog
fonte