Me gustaría fusionar dos bloques de líneas en Vim, es decir, tomar líneas n..my 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?

xcon 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,8antesdely1,4antes des///especificar en qué líneas operan los comandos.delelimina 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) | nohlsparece 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,:movey:joinlos 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.:movey: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:
jjCTRL-v$CTRL-ENDxkk$pEl 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:
abcydef) tienen la misma longitud XORfuente
abcydeftienen 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/ \+/ /gset ve=alldeberí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:
qagraba todo hasta el siguienteqen un "búfer" ena.macrea una marca en la línea actual.:5<CR>va al siguiente grupo.y$tira del resto de la línea.'avuelve a la marca, establecida anteriormente.$ppastas al final de la línea.:5<CR>vuelve a la primera línea del segundo grupo.ddlo borra'avuelve a la marca.jqbaja una línea y detiene la grabación.3@arepite la acción para cada línea (3 en mi caso)fuente
[Enter]después de las:5dos veces que lo escribes o esto no funcionará.:norm qama:5<CR>y$'a$p:5<CR>dd'ajq3@apero parece que solo se ejecutaq.:let @a="ma:5^My$'a$p:5^Mdd'aj" | normal 4@a, donde los^Mcaracteres 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 5Este método se basa en la línea de comandos de UNIX. La
pasteutilidad se creó para manejar este tipo de fusión de líneas.fuente
paste -dcomportamiento 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:
qacomienza a grabar una repetición compleja ena}salta a la siguiente línea vacíajddelimina la siguiente línea''vuelve a la posición anterior al último saltoppegue la línea eliminada debajo de la actualkJagregue la línea actual al final de la anteriorxeliminar el espacio que seJagrega entre las líneas combinadas; puedes omitir esto si quieres el espaciojpasa a la siguiente líneaqfinalizar la compleja grabación repetidaDespués de eso, usaría
@apara 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