Possível explicação do problema
Eu acho que a razão pela qual :g/;/jnão funciona é porque o :gcomando 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, :gjunta 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, :gprocura 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 :gencontra 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 :joinque, 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,bonde ae bgeralmente são 2 números de linha e permite operar em um grupo de linhas cujo número está entre ae b, em vez de apenas um.
Portanto, o jcomando 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/;/jnão funciona porque é feito em duas passagens: primeiro o buffer é verificado, depois o comando é aplicado às linhas correspondentes.