No meu código fortran, tenho muitos blocos como os seguintes
subroutine name(arg1,arg2,arg3,...)
:
end subroutine
e eu quero que eles se tornem
subroutine name(arg1,arg2,arg3,...)
:
end subroutine name
Onde cada um desses blocos pode ser indentado por qualquer quantidade de espaços (na verdade, esses blocos podem ser aninhados). Eu tentei com o comando
:g/^ *subroutine \(.*\)/;/end subrout/s/end subroutine/& \1
que muda cada linha (eu li na linha de fundo) mudando nada, assim como o buffer \1
está vazio. O comando
:g/^ *subroutine \(.*\)/;/end subrout/s/end subroutine/& hello
funciona bem, mas obviamente não é o que eu quero. Portanto, a pergunta é: como posso usar na sequência de substituição um padrão correspondido pelo comando ex global :g
?
EDIT Estou editando a pergunta, pois, no momento em que a publiquei, aceitei rapidamente a resposta que era uma resposta ao caso específico a que me referi, mas não ao título da pergunta, que é um pouco mais geral.
Eu vou direto ao ponto. Eu tenho um arquivo como o seguinte (não faz sentido apenas para torná-lo o mais genérico possível):
# sec1
fun1 are you a function?
fun2 no.
fun3 ok, nice to meet you!
# 2nd part
first line
third line
ops (it was the second)
there were 3 lines in the preceding #
# fourth group
now there's just one
and foreveeer
(De fato, as linhas que seguem cada #
linha são centenas.)
Eu tenho que fazer substituições em cada linha após cada #
linha (e precedendo a seguinte #
linha); todas essas substituições devem usar o texto após a #
linha de frente (ou parte dela). Um exemplo de desejo que eu gostaria de alcançar é
# sec1
fun1 in sec1 are you a function?
fun2 in sec1 no.
fun3 in sec1 ok, nice to meet you!
# 2nd part
first in 2nd line
third in 2nd line
ops in 2nd (it was the second)
there in 2nd were 3 lines in the preceding #
# fourth group
now in fourth there's just one
and in fourth foreveeer
Observe que apenas a primeira palavra a seguir #
é inserida nas seguintes linhas.
Então, como eu já disse, gostaria de saber se o padrão do :g
comando pode ser usado na cadeia de caracteres substituta. Estou muito interessado nesta resposta, pois é muito irritante registrar uma macro (pressionar uma tecla errada significa começar tudo de novo!), Enquanto um comando como esse,
:g/^# \(\<\w\+\>\)/+;/^#/- s/\(\<\w\+\>\)\(.\+$\)/\2 \1 \3
seria perfeito! ... E é difícil para mim acreditar que não há como usar um comando que faça o trabalho!
fonte
norm!
mata%
dematchit
. Solução::%g/^\s*subroutine/norm ^whye^%$p
.norm
vez denorm!
, pois estava bastante confiante de que não havia nenhuma configuração personalizada interferindo aqui ... Boa captura e obrigado pela correção.:%g
. Tentei tanto em um buffer com sub-rotinas distintas e aninhadas (e com-u NONE
) e obtive os mesmos resultados em ambos os casos. Embora:global
o intervalo padrão fosse1,$
(ie%
). Em que caso a%
diferença faria?Uma solução possível é usar uma macro:
Que pode ser detalhado como este:
Em seguida, você pode executar sua macro com
X@a
ondeX
está o número de sub-rotinas para prosseguirfonte
Aqui está a solução macro do @statox , modificada para lidar com parâmetros de sub-rotina e sub-rotinas aninhadas. Isso pressupõe que você também instalou o matchit :
@a
@a
/^\s*subroutine\zs<CR>
- procurarsubroutine
;\zs
deixa o cursor no espaço a seguir2
porque queremos incluir o espaço,w
porque queremos umword
(isso para em(
etc.)subroutine
end subroutine
(três aplausos paramatchit
)end
subroutine
subroutine
ssubroutine
na linha atualPara executá-lo:
:set nowrapscan
- evite um loop infinito: a macro será resgatada quando atingir a parte inferior do arquivofonte
Você pode usar um comando substituto:
Isso corresponde ao todo
subroutine / end subroutine
no grupo 1 e ao nome da sub-rotina no grupo 2 e concatena-os.O
{-}
é um não-ganancioso,*
então ele irá parar no primeiro elemento encontrado.\_.
combinar tudo e anew-line
.fonte
matchit
pode lidar com sub-rotinas aninhadas.