Me gustaría fusionar dos bloques de líneas en Vim, es decir, tomar líneas n..m
y agregarlas a líneas a..b
. Si prefiere una explicación de pseudocódigo:[a[i] + b[i] for i in min(len(a), len(b))]
Ejemplo:
abc
def
...
123
45
...
debe convertirse
abc123
def45
¿Hay una buena manera de hacer esto sin copiar y pegar manualmente?
x
con unirsex+2
?[a[i] + b[i] for i in min(len(a), len(b))]
Respuestas:
Ciertamente puede hacer todo esto con una sola copia / pegar (usando la selección de modo de bloque), pero supongo que eso no es lo que quiere.
Si quieres hacer esto con solo comandos Ex
transformará
dentro
ACTUALIZACIÓN: Una respuesta con tantos votos a favor merece una explicación más completa.
En Vim, puede usar el carácter de canalización (
|
) para encadenar múltiples comandos Ex, por lo que lo anterior es equivalente aMuchos comandos Ex aceptan un rango de líneas como argumento de prefijo; en el caso anterior,
5,8
antesdel
y1,4
antes des///
especificar en qué líneas operan los comandos.del
elimina las líneas dadas. Puede tomar un argumento de registro, pero cuando no se proporciona uno, volca las líneas en el registro sin nombre@"
, tal como lo hace la eliminación en modo normal.let l=split(@")
luego divide las líneas eliminadas en una lista, utilizando el delimitador predeterminado: espacios en blanco. Para funcionar correctamente en la entrada que tenía espacios en blanco en las líneas eliminadas, como:tendríamos que especificar un delimitador diferente, para evitar que "el trabajo es" de ser dividida en dos elementos de la lista:
let l=split(@","\n")
.Finalmente, en la sustitución
s/$/\=remove(l,0)/
, reemplazamos el final de cada línea ($
) con el valor de la expresiónremove(l,0)
.remove(l,0)
altera la listal
, eliminando y devolviendo su primer elemento. Esto nos permite reemplazar las líneas eliminadas en el orden en que las leemos. En su lugar, podríamos reemplazar las líneas eliminadas en orden inverso mediante el usoremove(l,-1)
.fuente
s/\s*$/
lugar des/$/
.:sil5,8del | let l=split(@") | sil1,4s/$/\=remove(l,0)/ | call histdel("/", -1) | nohls
parece ser aún mejor ya que limpia el historial de búsqueda después de la ejecución. Y no muestra el mensaje "x más / menos líneas" que requiere que presione enter.:help range
,:help :d
,:help :let
,:help split()
,:help :s
,:help :s\=
,:help remove()
.Un comando elegante y concisa Ex solución del problema puede ser obtenida mediante la combinación de los
:global
,:move
y:join
los comandos. Suponiendo que el primer bloque de líneas comienza en la primera línea del búfer y que el cursor se encuentra en la línea que precede inmediatamente a la primera línea del segundo bloque, el comando es el siguiente.Para obtener una explicación detallada de esta técnica, vea mi respuesta a una pregunta similar ¿ Comportamiento de “ pegar Vim -d” fuera de la caja? ".
fuente
E16: Invalid Range
- Pero funciona de todos modos. Al eliminar el1,
funciona sin el error.:move
y:join!
, ni qué''
significaba como argumento de rango (:help ''
) y qué+
y-
significaba como modificadores de rango (:help range
). ¡Gracias!sil!
el comando.Para unir bloques de línea, debe realizar los siguientes pasos:
jj
CTRL-v
$
CTRL-END
x
kk$
p
El movimiento no es el mejor (no soy un experto), pero funciona como quisieras. Espero que haya una versión más corta de la misma.
Estos son los requisitos previos para que esta técnica funcione bien:
abc
ydef
) tienen la misma longitud XORfuente
abc
ydef
tienen la misma longitud. La selección de bloque mantendrá las sangrías del texto eliminado, por lo que si el cursor se encuentra en una línea corta al colocar el texto, las líneas se insertan entre las letras en las más largas, y los espacios se añaden a las más cortas si el cursor era más largo uno.:%s/ \+/ /g
set ve=all
debería ayudar, consulte vimdoc.sourceforge.net/htmldoc/options.html#'virtualedit 'Así es como lo haría (con el cursor en la primera línea):
Necesitas saber dos cosas:
Esto es lo que está pasando:
qa
graba todo hasta el siguienteq
en un "búfer" ena
.ma
crea una marca en la línea actual.:5<CR>
va al siguiente grupo.y$
tira del resto de la línea.'a
vuelve a la marca, establecida anteriormente.$p
pastas al final de la línea.:5<CR>
vuelve a la primera línea del segundo grupo.dd
lo borra'a
vuelve a la marca.jq
baja una línea y detiene la grabación.3@a
repite la acción para cada línea (3 en mi caso)fuente
[Enter]
después de las:5
dos veces que lo escribes o esto no funcionará.:norm qama:5<CR>y$'a$p:5<CR>dd'ajq3@a
pero parece que solo se ejecutaq
.:let @a="ma:5^My$'a$p:5^Mdd'aj" | normal 4@a
, donde los^M
caracteres se escriben presionando CTRL-V y luego Enter.Como se mencionó en otra parte, la selección de bloques es el camino a seguir. Pero también puede usar cualquier variante de:
:!tail -n -6 % | paste -d '\0' % - | head -n 5
Este método se basa en la línea de comandos de UNIX. La
paste
utilidad se creó para manejar este tipo de fusión de líneas.fuente
paste -d
comportamiento deseado ( similar) se puede implementar mediante un breve comando Vim, como se muestra en mi respuesta .Los datos de muestra son los mismos que los de rampion.
fuente
No creo que sea demasiado complicado. Simplemente establecería virtualedit en
(
:set virtualedit=all
)Seleccione el bloque 123 y todo lo siguiente.
Ponlo después de la primera columna:
y elimine el espacio múltiple entre 1 espacio:
fuente
gvV:'<,'>s/\s+//g
(vim debería insertarlo automáticamente'<,'>
para que no necesite escribirlo manualmente).Usaría repeticiones complejas :)
Dado este:
Con el cursor en la primera línea, presione lo siguiente:
y luego presione
@a
(y luego puede usar@@
) tantas veces como sea necesario.Deberías terminar con:
(Además de una nueva línea).
Explicacion:
qa
comienza a grabar una repetición compleja ena
}
salta a la siguiente línea vacíajdd
elimina la siguiente línea''
vuelve a la posición anterior al último saltop
pegue la línea eliminada debajo de la actualkJ
agregue la línea actual al final de la anteriorx
eliminar el espacio que seJ
agrega entre las líneas combinadas; puedes omitir esto si quieres el espacioj
pasa a la siguiente líneaq
finalizar la compleja grabación repetidaDespués de eso, usaría
@a
para ejecutar la repetición compleja almacenada ena
, y luego puede usar@@
para volver a ejecutar la última repetición compleja ejecutada.fuente
Puede haber muchas formas de lograr esto. Combinaré dos bloques de texto usando cualquiera de los siguientes dos métodos.
supongamos que el primer bloque está en la línea 1 y el segundo bloque comienza en la línea 10 con la posición inicial del cursor en la línea número 1.
(\ n significa presionar la tecla Intro).
con una macro usando los comandos: copiar, pegar y unir.
con una macro usando los comandos, mueva una línea en el enésimo número de línea y únase.
fuente