Vim - Agregar línea vacía entre líneas

15

¿Cómo inserto una línea en blanco entre cada línea que no está en blanco?

p.ej. desde

line 1
line 2
line 3

line 4
line 5

a

line 1

line 2

line 3

line 4

line 5
ayutheos
fuente

Respuestas:

27

El comando de Vim: g está diseñado para exactamente este tipo de tarea; ejecutar una sola acción en cada línea que coincida con un patrón particular. Aquí está mi respuesta:

:g/.\n\n\@!/norm o

El patrón que uso es /.\n\n\@!/. Desglosando eso en sus piezas componentes:

  • .Coincide con cualquier personaje de la línea. (Se utiliza para descartar de inmediato cualquier línea vacía existente)
  • \n Coincide con un solo \ n al final del carácter anterior
  • \n\@! Falla la coincidencia si hay otra \ n inmediatamente después de la \ n anterior.

(Busque :h E59más información sobre \@!especificadores de coincidencias similares en expresiones regulares; ¡también hay un par más!)

Por lo tanto, la expresión regular del comando: g ahora ha seleccionado cada línea no vacía que termina con una nueva línea nueva, y que no es seguida por una línea vacía.

Después del patrón en una :gdeclaración viene el comando para ejecutarse en líneas coincidentes. En este caso, le he dicho que ejecute un comando en modo normal (abreviado como norm), y el comando para ejecutar es simplemente o, que inserta una línea vacía debajo de la línea actual.

En conjunto, el comando encuentra todas las líneas que no tienen una línea vacía debajo y agrega una. ¡Y eso es todo! Es posible que desee consultar el artículo Power of G de vim wiki para obtener más cosas elegantes que puede hacer :g(y es una hermana negativa :v): es uno de esos comandos increíblemente útiles en los que pronto se puede confiar, y luego se pierde terriblemente en los editores que no lo tengo

Trevor Powell
fuente
1
Precisamente. Por lo general, busco shorthands como, :%norm opero resulta que esto no funciona según lo previsto en el caso de o. +1
sehe
Escribe :%s/$/, luego presiona ^V, luego presiona Enter.
jpaugh
1
@jpaugh Suponiendo que te refieres :%s/$/<C-V><CR><CR>(para usar la codificación común vim-folk de las pulsaciones de teclas), ese enfoque solo agrega una nueva línea después de cada línea. Es decir, las líneas que ya están separadas por espacios en blanco (ver Línea 3 -> Línea 4, en el texto de ejemplo) terminan obteniendo líneas en blanco adicionales. La pregunta original era evitar agregar líneas en blanco adicionales donde ya existían en el texto inicial.
Trevor Powell
3

Cuando probé la búsqueda global de @ NeilForester y la respuesta de reemplazo, descubrí que se perdía cada segundo reemplazo previsto en líneas consecutivas no en blanco si las líneas solo tenían un carácter en cada una. Esto parece deberse a que el patrón comienza a coincidir en cada ocasión después del último personaje que coincidió con la ocasión anterior.

Usar lookbehind y lookahead resuelve este problema y también hace que la expresión regular sea un poco más corta:

:%s/\n\@<!\n\n\@!/\r\r/g
Simón
fuente
¡Gracias! Esto funciona, y no agrega más líneas si ejecuto la búsqueda nuevamente (si dice, agregué nuevas líneas en mi archivo).
1
¿Podría explicar qué significa cada una de las expresiones regulares en el patrón de búsqueda? Mirando vim help, ¿ \n\@<!\nsignifica que cualquier salto de línea que no sea correcto después de otro salto de línea es correcto? Pero no pude entender lo que \n\@!significa. Me gustaría entenderlo para poder aprenderlo y aplicarlo a otros patrones de búsqueda :)
Sí, \n\@<!\nsignifica cualquier salto de línea que no sigue inmediatamente a otro salto de línea. \n\@!coincide con el ancho cero si el átomo anterior (es decir \n) no coincide justo antes de lo que sigue. Intente :help \@<!ver la documentación sobre esto en vim. I
Simon
3

De otra manera:

%s/\(.\)\n\(.\)/\1\r\r\2/

Lo que significa,

\(.\) match and capture a non-newline character,
\n    match a newline
\(.\) match and capture a non-newline character

reemplace con: primera captura, nuevas líneas dobles y la segunda captura.

Por ejemplo, line1\nLine2resultados en \1 = 1y \2 = L.

perreal
fuente
0

Corrígeme si estoy equivocado. Creo que usa la letra k cuando está en modo comando para moverse hacia abajo en una línea. Luego ingrese al modo de inserción y agregue la siguiente línea. ¿Repetir según sea necesario? ¡Espero que esto ayude!

Nick Gerrer
fuente
ksube una línea jbaja una línea
Neil Forrester
Sí, de hecho lo hace. Mi error. Gracias Neil!
0
/[^\n]\n[^\n]
:map <F2> no<esc><F2>

Luego presione <F2>. Eso buscará dos líneas consecutivas que no estén en blanco y luego agregará una línea entre ellas, repetidamente.

Editar:

Aquí hay una forma alternativa de hacerlo con una única búsqueda global y reemplazo:

:%s/\([^\n]\)\n\([^\n]\)/\1\r\r\2/g
Neil Forrester
fuente
Mi archivo tiene muchas líneas. ¿Hay alguna manera de hacer una búsqueda de expresiones regulares e insertar una línea en blanco para todo el archivo? He estado mirando stackoverflow.com/questions/2673209/… pero no pude entender lo que significan todos los comandos de expresiones regulares.
Vea mi edición anterior para una forma alternativa de lograr lo mismo en un solo comando, y sin un mapeo recursivo. Sin embargo, la primera forma debería funcionar para todo el archivo.
Neil Forrester
0

Pruebe este comando ( 16caracteres):

:%!sed G|cat -s
kev
fuente
En lugar de intentar "vimgolf" un comando corto, sería más útil una pequeña explicación de las opciones poco claras utilizadas.
Ingo Karkat
0

No sé cuánto dura su archivo, pero uno de los métodos más simples es escribir oen modo comando. Y en la siguiente línea .. Esto podría cargarse a una macro simple.

Demagógico
fuente