Substituir texto da linha acima no Vim
Pergunta
Como posso substituir os primeiros caracteres dez de uma linha onde os personagens dez correspondem a um padrão particular, com os primeiros caracteres de dez a partir da linha acima?
Edit: Não estava claro se eu estava pedindo para substituir os primeiros caracteres dez onde o jogo poderia aparecer em qualquer lugar dentro da linha, então talvez fazer uma nota em sua resposta se ele lida com este caso (chamada neste caso B e a destinar um caso a?)
Solução
Prehaps:
:%s/^\(.\{10}\)\(.*\n\)abcdefghij\(.*\)/\1\2\1\3/
Onde abcdefghij 'é a seqüência de 10 caracteres na 2ª linha
Outras dicas
Algo como isso iria funcionar:
%s/^.\{10\}/\=strpart(get(getbufline("", line(".")-1), 0, ""), 0, 10)/
onde ^.\{10\}
é o seu padrão real.
%s/ # substitute all lines matching…
^.\{10\} # your pattern
/ # …with…
\= # an expression:
strpart( # gets the part of a string
get( # gets an element of a list
getbufline( # gets a list of lines from the current buffer
"", line(".")-1) # getbufline() the line before the current line
, 0, "") # get() first line in buffer, default to ""
, 0, 10) # strpart() first ten characters
/ # …end of substitution
:2,$g/<pattern>/s/^.\{10}/\=strpart(getline(line(".")-1),0,10)
-
2,$
é a nossa gama (como a primeira linha não tem nenhuma linha anterior) -
g//
permite executar um comando em linhas que correspondem a um determinado padrão. -
s/^.\{10}/
irá substituir os 10 primeiros caracteres de uma linha -
\=
permite substituir o resultado de uma expressão vim em uma:s//
-
line(".")
é o número da linha atual -
getline(line(".")-1)
é o texto da linha anterior -
strpart(getline(line(".")-1),0,10)
é os primeiros 10 caracteres da linha anterior
Por exemplo 2,$g/frog/s/^.\{10}/\=strpart(getline(line(".")-1),0,10)
vai mudar:
I like eating mangos before frying frogs legs I wish I had a puppy She gave Dad a frog
Para isto:
I like eating mangos I like eating frogs legs I wish I had a puppy I wish I had a frog
Se eu tiver uma ação complexa como a que eu costumo gravar uma macro usando o comando q
. Algo como (não testado):
/<pattern>
qq
10x
k
10yl
j
P
n
q
E problema, então repeatedy que macro como @q
opcionalmente prefixados com uma contagem.
Você pode usar pesquisa e substituição:
:7,9 s/foo/bar/c
Este exemplo pesquisas de linha 7 a 9 para cada ocorrência de 'foo', e substitui-lo por 'bar', pedindo uma confirmação em cada hit. Se você não quiser confirmar, soltar o c no final. Escolha o intervalo como você vê o ajuste e isso deve chegar onde você quer
Usando movimentos e puxando única do vim / colar .. Dado o conteúdo ..
arquivo1234567890abcdef
qwertyuiopasdfgh
Com o cursor em q, 10x
, arquivo torna-se:
1234567890abcdef
asdfgh
Mova o cursor para a primeira linha (usando k
irá fazê-lo), então faça 10yl
(Yank 10 caracteres, direita)
Em seguida, voltar para baixo uma linha, j
, e cole P
(maiúsculas, para colar sob o cursor) eo arquivo torna-se:
1234567890abcdef
1234567890asdfgh
Em suma, começando com o cursor em q:
10xk10yljP
.. que você pode colar no, ou atribuir a uma macro
Seria mais curto, se houve um atalho óbvio para colar, substituindo, mas eu não poderia encontrar tal coisa um
Uma outra opção é uma pesquisa regex incrivelmente obscuros procurando / substituir ..
Visual-line selecione as duas linhas de destino e execute o seguinte pesquisa e substituição:
:'<,'>s/\(\(.\{10\}\).*\)\n\(.\{10\}\)\(.*\)$/\1\r\2\4/
Basicamente ele pega ..
-
\1
- toda a primeira linha -
\2
- os primeiros 10 caracteres (em um grupo aninhado) - uma quebra de linha
-
\3
- os primeiros caracteres dez de linha dois -
\4
- o resto da segunda linha
Em seguida, constrói as duas linhas como \1\n\2\4
- primeira linha completa, quebra de linha, os 10 primeiros caracteres de primeira, de segunda restante