Posible explicación del problema.
Creo que la razón por la :g/;/j
que no funciona es porque el :g
comando funciona con un algoritmo de 2 pasos:
- durante la primera pasada marca las líneas que contienen el patrón
;
- durante la segunda pasada opera en las líneas marcadas
Durante la segunda pasada, :g
une la línea 1;
con la línea 2;
porque 1;
se marcó durante la primera pasada. Sin embargo, sospecho (no estoy seguro) que no se une 1; 2;
con 3;
ya que la línea 2;
ya no existe, su contenido se ha fusionado con la línea 1;
que ya ha sido procesado.
Entonces :g
busca la siguiente línea que se marcó durante el primer pase ( 3;
) y la une con la siguiente ( 4;
). Después de eso se repite el problema, no pueden unirse 3; 4;
con 5;
porque la línea 4;
no existe más.
Solución 1 (con vimscript)
Tal vez podría llamar a una función siempre que ;
se encuentre una línea que contenga para verificar si la línea anterior también contiene un punto y coma:
function! JoinLines()
if getline(line('.')-1) =~ ';'
.-1join
endif
endfunction
Luego use el siguiente comando global:
:g/;/call JoinLines()
O sin una función:
:g/;/if getline(line('.')-1) =~ ';' | -j | endif
Solución 2 (sin vimscript)
:g/;/.,/^[^;]*$/-1j
Cada vez que el comando global :g
encuentra el patrón ;
, ejecuta el comando: .,/^[^;]*$/-1j
Se puede desglosar así:
:g/pattern/a,bj
Dónde :
pattern = ;
a = . = number of current line
b = /^[^;]*$/-1 = number of next line without any semicolon minus one
b
puede desglosarse más de esta manera:
/ = 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
es la forma abreviada del comando Ex :join
que, como la mayoría de los otros comandos Ex, puede ir precedida de un rango.
Aquí está precedido por el rango: .,/^[^;]*$/-1
( a,b
)
Un rango sigue la forma a,b
donde a
y b
generalmente son números de 2 líneas, y le permite operar en un grupo de líneas cuyo número está entre a
y b
, en lugar de solo uno.
Entonces, el j
comando une todas las líneas entre la actual ( a
) y la siguiente que no contiene punto y coma menos uno ( b
).
Para más información, ver:
:help :global
:help :join
:help :range
:g/;/j
no funciona porque se realiza en dos pasadas: primero se escanea el búfer, luego se aplica el comando a las líneas coincidentes.