No meu código fortran, tenho muitos blocos como os seguintes
e eu quero que eles se tornem
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
que muda cada linha (eu li na linha de fundo) mudando nada, assim como o buffer \1está vazio. O comando
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):
(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 é
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 :gcomando 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,
seria perfeito! ... E é difícil para mim acreditar que não há como usar um comando que faça o trabalho!
Você pode usar uma combinação de :global, matchit e :normal!:
:g/^\s*subroutine: para todas as linhas correspondentes ^\s*subroutine, faça:
normal: entra no modo normal (! significa que não há mapeamentosque não usam norm!, como o !remove a chamada para matchit (graças @SatoKatsura))
^vá para o primeiro caractere não em branco (não 0, para manipular sub-rotinas aninhadas)
whye: vá para a segunda palavra (nome), volte 1 caractere (espaço) e copie-o (o espaço é para facilitar um pouco a colagem no final)
^%: volte para o primeiro caractere não em branco e use matchit para encontrar a correspondência end
$p: colar name(com um espaço em branco à esquerda) no final da linha
norm!mata %de matchit. Solução: :%g/^\s*subroutine/norm ^whye^%$p.
Ah, você está certo. Na verdade, eu testei, mas usei em normvez de norm!, pois estava bastante confiante de que não havia nenhuma configuração personalizada interferindo aqui ... Boa captura e obrigado pela correção.
— 27716 Marth
@SatoKatsura: Não vejo por que você precisa usar :%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 :globalo intervalo padrão fosse 1,$(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@aonde Xestá o número de sub-rotinas para prosseguir
Bem, eu uso muitas macros (registre c para comentar, u para descomentar, t para tab e assim por diante), para que mais uma macro não seja um problema. De qualquer forma, meu ponto de vista é que eu poderia sobrescrever erroneamente a macro com algo sem sentido, mesmo sem perceber (q está perto de we ainda não sou um mestre em digitação por toque). Então, por enquanto, espero / espero por outras respostas.
Fortran pode ter sub-rotinas aninhadas.
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 :
qaq - registro claro @a
qa - iniciar a gravação no registro @a
/^\s*subroutine\zs<CR>- procurar subroutine; \zsdeixa o cursor no espaço a seguir
y2w- arranque o nome; 2porque queremos incluir o espaço, wporque queremos um word(isso para em (etc.)
h - vá para a esquerda, até o final de subroutine
%- ir para correspondência end subroutine(três aplausos para matchit)
$p - cole o nome
_ - vá para o primeiro caractere não em branco, ou seja, o início de (the) end
% - de volta à correspondência subroutine
j- para baixo, para procurar mais subroutines
0- vá para o início da linha, para não perder um subroutinena linha atual
@a - chamar a macro atual recursivamente
q - macro final
:set nowrapscan - evite um loop infinito: a macro será resgatada quando atingir a parte inferior do arquivo
1G - ir para o topo do arquivo
@a - executar macro
Você pode usar um comando substituto:
Isso corresponde ao todo subroutine / end subroutineno 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 a new-line.
Isso não vai funcionar, o Fortran pode ter sub-rotinas aninhadas.
Eu sei, mas o OP não especificou nada sobre isso. Sua proposição e a outra resposta não funcionarão com sub-rotinas aninhadas. A sub-rotina de "fechamento" correspondente é outra questão.