Eu gostaria de mesclar dois blocos de linhas no Vim, ou seja, pegar linhas n..m
e anexá-las às linhas a..b
. Se você preferir uma explicação de pseudocódigo:[a[i] + b[i] for i in min(len(a), len(b))]
Exemplo:
abc
def
...
123
45
...
Deve se tornar
abc123
def45
Existe uma boa maneira de fazer isso sem copiar e colar manualmente?
x
com joinx+2
?[a[i] + b[i] for i in min(len(a), len(b))]
Respostas:
Você certamente pode fazer tudo isso com uma única cópia / pasta (usando a seleção do modo de bloco), mas acho que não é isso que você deseja.
Se você quiser fazer isso apenas com comandos Ex
vai transformar
para dentro
ATUALIZAÇÃO: Uma resposta com tantos votos positivos merece uma explicação mais completa.
No Vim, você pode usar o caractere de barra vertical (
|
) para encadear vários comandos Ex, portanto, o acima é equivalente aMuitos comandos Ex aceitam um intervalo de linhas como argumento de prefixo - no caso acima, o
5,8
antesdel
e o1,4
antes das///
especificação de quais linhas os comandos operam.del
exclui as linhas fornecidas. Pode levar um argumento de registro, mas quando um não é fornecido, ele despeja as linhas no registro sem nome@"
, assim como a exclusão no modo normal.let l=split(@")
depois divide as linhas excluídas em uma lista, usando o delimitador padrão: espaço em branco. Para funcionar corretamente em entradas com espaços em branco nas linhas excluídas, como:tínhamos necessidade de especificar um delimitador diferente, para evitar que "o trabalho é" de ser dividido em dois elementos da lista:
let l=split(@","\n")
.Finalmente, na substituição
s/$/\=remove(l,0)/
, substituímos o final de cada linha ($
) pelo valor da expressãoremove(l,0)
.remove(l,0)
altera a listal
, excluindo e retornando seu primeiro elemento. Isso nos permite substituir as linhas excluídas na ordem em que as lemos. Em vez disso, poderíamos substituir as linhas excluídas na ordem inversa usandoremove(l,-1)
.fonte
s/\s*$/
vez des/$/
.:sil5,8del | let l=split(@") | sil1,4s/$/\=remove(l,0)/ | call histdel("/", -1) | nohls
parece ser ainda melhor, pois limpa o histórico de pesquisas após a execução. E não mostra a mensagem "x mais / menos linhas" exigindo que eu pressione enter.:help range
,:help :d
,:help :let
,:help split()
,:help :s
,:help :s\=
,:help remove()
.Um comando elegante e conciso Ex resolver o problema pode ser obtido através da combinação das
:global
,:move
e:join
comandos. Supondo que o primeiro bloco de linhas inicie na primeira linha do buffer e que o cursor esteja localizado na linha imediatamente anterior à primeira linha do segundo bloco, o comando é o seguinte.Para uma explicação detalhada dessa técnica, consulte minha resposta para uma pergunta semelhante “ Vim colar comportamento de d '' fora da caixa? ”.
fonte
E16: Invalid Range
- mas funciona de qualquer maneira. Ao remover o1,
que funciona sem o erro.:move
e:join!
, nem o que''
significava como um argumento de intervalo (:help ''
) eo que+
e-
concebida como modificadores de alcance (:help range
). Obrigado!sil!
o comando.Para unir blocos de linha, você deve executar as seguintes etapas:
jj
CTRL-v
$
CTRL-END
x
kk$
p
O movimento não é o melhor (não sou especialista), mas funciona como você queria. Espero que haja uma versão mais curta dele.
Aqui estão os pré-requisitos para que essa técnica funcione bem:
abc
edef
) têm o mesmo comprimento XORfonte
abc
edef
tem o mesmo comprimento. A seleção de blocos manterá os recuos do texto excluído; portanto, se o cursor estiver em uma linha curta ao colocar o texto, as linhas serão inseridas entre as letras nas mais longas - e os espaços serão acrescentados às mais curtas se o cursor estiver mais longo. 1.:%s/ \+/ /g
set ve=all
deve ajudar, consulte vimdoc.sourceforge.net/htmldoc/options.html#'virtualedit 'Aqui está como eu faria isso (com o cursor na primeira linha):
Você precisa saber duas coisas:
Aqui está o que está acontecendo:
qa
registra tudo até o próximoq
em um "buffer" ema
.ma
cria uma marca na linha atual.:5<CR>
vai para o próximo grupo.y$
puxa o resto da linha.'a
retorna à marca, defina anteriormente.$p
pastas no final da linha.:5<CR>
retorna à primeira linha do segundo grupo.dd
exclui.'a
retorna à marca.jq
desce uma linha e para de gravar.3@a
repete a ação para cada linha (3 no meu caso)fonte
[Enter]
após as:5
duas vezes que digitar ou isso não funcionará.:norm qama:5<CR>y$'a$p:5<CR>dd'ajq3@a
mas isso parece executar apenasq
.:let @a="ma:5^My$'a$p:5^Mdd'aj" | normal 4@a
, onde os^M
caracteres são digitados pressionando CTRL-V e depois Enter.Como mencionado em outro lugar, a seleção de blocos é o caminho a percorrer. Mas você também pode usar qualquer variante de:
:!tail -n -6 % | paste -d '\0' % - | head -n 5
Este método depende da linha de comandos do UNIX. O
paste
utilitário foi criado para lidar com esse tipo de mesclagem de linhas.fonte
paste -d
comportamento ( como) desejado pode ser implementado por meio do comando Vim curto, como mostrado na minha resposta .Os dados de amostra são os mesmos que os de rampion.
fonte
Eu não acho que tornaria isso muito complicado. Gostaria apenas de definir virtualedit em
(
:set virtualedit=all
)Selecione o bloco 123 e tudo abaixo.
Coloque-o após a primeira coluna:
e remova o espaço múltiplo entre 1 espaço:
fonte
gvV:'<,'>s/\s+//g
(o vim deve inserir automaticamente o'<,'>
para você, para que você não precise digitá-lo manualmente).Eu usaria repetições complexas :)
Dado isto:
Com o cursor na primeira linha, pressione o seguinte:
e pressione
@a
(e você poderá usá-lo posteriormente@@
) quantas vezes for necessário.Você deve terminar com:
(Mais uma nova linha.)
Explicação:
qa
começa a gravar uma repetição complexa ema
}
pula para a próxima linha vaziajdd
exclui a próxima linha''
volta à posição anterior ao último saltop
cole a linha excluída sob a atualkJ
anexar a linha atual ao final da linha anteriorx
exclua o espaço queJ
adiciona entre as linhas combinadas; você pode omitir isso se quiser o espaçoj
vá para a próxima linhaq
terminar a gravação repetida complexaDepois disso, você usaria
@a
para executar a repetição complexa armazenadaa
e, em seguida, poderá@@
executar novamente a última repetição complexa executada.fonte
Pode haver várias maneiras de conseguir isso. Mesclarei dois blocos de texto usando qualquer um dos dois métodos a seguir.
suponha que o primeiro bloco esteja na linha 1 e o segundo bloco comece na linha 10 com a posição inicial do cursor na linha número 1.
(\ n significa pressionar a tecla Enter.)
com uma macro usando os comandos: copiar, colar e participar.
com uma macro usando os comandos, mova uma linha no enésimo número da linha e junte-se.
fonte