Me gustaría unir líneas solo para líneas que tienen cierto patrón (como ;
), sin embargo, cuando g/;/j
se usa no funciona como se espera a menos que se llame un par de veces.
Por ejemplo el siguiente contenido:
a
1;
2;
3;
4;
5;
b
6;
7;
8;
9;
c
cuando se usa: :g/;/j
la salida es:
a
1; 2;
3; 4;
5; b
6; 7;
8; 9;
c
o :g/;/-j
da:
a 1; 2; 3; 4; 5;
b 6; 7; 8; 9;
c
similar con: :g/;\_.\{-};/j
.
Mi salida esperada es:
a
1; 2; 3; 4; 5;
b
6; 7; 8; 9;
c
o algo similar, por lo que todas las líneas que contienen el patrón se unen.
¿Cómo se puede lograr esto?
global-command
kenorb
fuente
fuente
: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.Respuestas:
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 segunda pasada,
:g
une la línea1;
con la línea2;
porque1;
se marcó durante la primera pasada. Sin embargo, sospecho (no estoy seguro) que no se une1; 2;
con3;
ya que la línea2;
ya no existe, su contenido se ha fusionado con la línea1;
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 unirse3; 4;
con5;
porque la línea4;
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:Luego use el siguiente comando global:
O sin una función:
Solución 2 (sin vimscript)
Cada vez que el comando global
:g
encuentra el patrón;
, ejecuta el comando:.,/^[^;]*$/-1j
Se puede desglosar así:
Dónde :
b
puede desglosarse más de esta manera: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
dondea
yb
generalmente son números de 2 líneas, y le permite operar en un grupo de líneas cuyo número está entrea
yb
, 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:
fuente
Hago uniones similares todo el tiempo con una búsqueda global y reemplazo:
\n
coincide con nueva línea.Para buscar y eliminar líneas en blanco:
No estoy seguro de por qué, pero si desea insertar una nueva línea, debe usar
\r
fuente
s
solo funcionará para una línea, para que sea global, debe usarla%s
, pero luego unirá casi todas las líneas, incluidas las que no son;
líneas:s
comando exactamente para lo que quieras. Creo que esto%s/;\n\(.*;\)\@=/;/
hace lo que necesitas.