Possível explicação do problema
Eu acho que a razão pela qual :g/;/j
não funciona é porque o :g
comando opera com um algoritmo de 2 passagens:
- durante a primeira passagem, ele marca as linhas que contêm o padrão
;
- durante o segundo passe, opera nas linhas marcadas
Durante a segunda passagem, :g
junta a linha 1;
com a linha 2;
porque 1;
foi marcada durante a primeira passagem. No entanto eu suspeito que (não tenho certeza) que não se juntar 1; 2;
com 3;
porque a linha 2;
não existe mais, o seu conteúdo tem sido fundida com a linha 1;
que já foi processado.
Então, :g
procura a próxima linha que foi marcada durante a primeira passagem ( 3;
) e a une à seguinte ( 4;
). Depois que se repete problema, ele não pode se juntar 3; 4;
com 5;
porque a linha 4;
não existe mais.
Solução 1 (com vimscript)
Talvez você possa chamar uma função sempre que uma linha contendo ;
for encontrada para verificar se a linha anterior também contém um ponto e vírgula:
function! JoinLines()
if getline(line('.')-1) =~ ';'
.-1join
endif
endfunction
Em seguida, use o seguinte comando global:
:g/;/call JoinLines()
Ou sem uma função:
:g/;/if getline(line('.')-1) =~ ';' | -j | endif
Solução 2 (sem vimscript)
:g/;/.,/^[^;]*$/-1j
Sempre que o comando global :g
encontra o padrão, ;
ele executa o comando: .,/^[^;]*$/-1j
Pode ser dividido assim:
:g/pattern/a,bj
Onde :
pattern = ;
a = . = number of current line
b = /^[^;]*$/-1 = number of next line without any semicolon minus one
b
pode ser dividido ainda mais assim:
/ = look for the number of the next line matching the following pattern
^ = a beginning of line
[^;] = then any character except a semicolon
* = the last character can be repeated 0 or more times
$ = an end of line
/ = end of pattern
-1 = removes one to the number you just got
j
é a forma abreviada do comando Ex :join
que, como a maioria dos outros comandos Ex, pode ser precedido por um intervalo.
Aqui, é precedido pelo intervalo: .,/^[^;]*$/-1
( a,b
)
Um intervalo segue a forma a,b
onde a
e b
geralmente são 2 números de linha e permite operar em um grupo de linhas cujo número está entre a
e b
, em vez de apenas um.
Portanto, o j
comando une todas as linhas entre a atual ( a
) e a próxima que não contém ponto e vírgula menos uma ( b
).
Para mais informações, veja:
:help :global
:help :join
:help :range
:g/;/j
não funciona porque é feito em duas passagens: primeiro o buffer é verificado, depois o comando é aplicado às linhas correspondentes.