Vim: pegar líneas línea por línea

8

Supongamos que tengo un archivo que contiene:

xxx
yyy
zzz

y otro archivo:

kkk
qqq
ppp

Quiero obtener:

xxxkkk
yyyqqq
zzzppp

¿Es eso posible en Vim con algún comando? (He intentado usar VISUAL BLOCK pero sin éxito).

En mi caso particular, tengo dos archivos grandes con muchas líneas para pegar, por lo que la respuesta también podría ser algún comando de shell, pero me gustaría saber si hay una manera de hacerlo incluso dentro del mismo archivo.

Fabio F.
fuente

Respuestas:

12

Desde la línea de comando, puedes intentar

paste -d '\0' file1 file2 > file3

Eso hace exactamente lo que quieres.

El modo Visual Block vimtambién es perfecto para esta tarea. ¿Estás seguro de que lo hiciste correctamente? Debieras

  • Ir al modo de bloqueo visual
  • Seleccione texto y presione ypara tirar
  • Vaya al otro archivo, en la esquina superior izquierda de los datos para pegar (último x) y presione p.
Bernhard
fuente
Estaba pegando en Visual Block ... eso es exactamente lo que quería hacer. Gracias.
Fabio F.
1
Al menos con GNU Coreutils, paste -d '' ...también funciona. Curiosamente, la página de manual y las páginas de información de coreutils parecen no documentar '\ 0', aunque se especifica en la especificación Single Unix.
derobert
5

Puedes hacerlo directamente al editar file1. Escriba :para cambiar command modeen vim. Luego escriba:

%!paste -d '' - file2
Cuonglm
fuente
3

Aquí hay una manera de hacerlo dentro del mismo archivo usando solo Vim.

Implica un mapeo de teclas. Se me ocurrió esto una vez cuando quise organizar varias listas en estructuras similares a tablas en texto simple.

Esto se basa en la tecla } (llave derecha) para omitir los límites de los párrafos. (Las llaves se reflejan, por cierto: { salta hacia la parte superior del archivo y } hacia el final).

Entonces ... suponga que tiene un archivo de datos como este (esto supone que las líneas # están activadas con : set nu ):

+---------------  
| 1 xxx    (cursor on line#1)  
| 2 yyy  
| 3 zzz  
| 4   
| 5 kkk  
| 6 qqq  
| 7 ppp  
+---------------  

Es importante que la línea # 4 sea una línea vacía (sin espacios en blanco), explicaré por qué en un momento.

Ejecute el siguiente mapa comando:
: mapa q mw} jdd'wpkJj

Esto vincula la tecla "q" a un programa de 12 caracteres, que detallaré a continuación con más detalle.

Cuando presionas "q" ejecutará ese programa; tenga en cuenta que su cursor, que comenzó en la línea 1, ahora está en la línea siguiente, listo para presionar "q" nuevamente. Es posible que haya notado que hay un espacio entre "xxx kkk"; si no quieres eso, mira "¿Qué pasa con el personaje extra espacial?" abajo, cerca del final.

+---------------
| 1 xxx kkk
| 2 yyy   (cursor on line #2)
| 3 zzz
| 4 
| 5 qqq
| 6 qqq
| ~
+---------------

Aquí hay un desglose de la asignación:

   :map q mw}jdd'wpkJj
   ^

Los dos puntos lo llevan al modo de comando para que podamos emitir el comando "mapa".

   :map q mw}jdd'wpkJj
    ^^^^^

mapa q une q con la siguiente secuencia de caracteres. Tenga en cuenta que "q" es solo mi tecla habitual "map to"; Puedes usar otras teclas. Por defecto, q minúscula se asigna para iniciar la grabación de macros; Como rara vez uso (¿nunca?), encuentro "q" más útil para las macros de utilidad únicas. También puede usar Q mayúscula (p. Ej., Mapa Q) o una tecla fnct, etc.

Ahora, cada vez que presione "q" (en modo de navegación), vim ejecutará esta serie de pulsaciones de teclas:

   mw}jdd'wpkJj

Lo cual, por supuesto, parece un galimatías total, por lo que lo desglosaré acción por acción (con ^^ a continuación) para que sea más fácil seguir lo que está sucediendo.

mw}jdd'wpkJj
^^

Los mw marca una ubicación con nombre, el nombre que aquí es 'w'. Uso 'w' por defecto (creo que es mi 'ubicación de trabajo'. Cualquier ubicación con nombre, desde az funcionaría, siempre y cuando sea coherente.
La 'w' volverá a aparecer en un momento cuando desea devolver el cursor a esta línea.

mw}jdd'wpkJj
  ^

Aquí tenemos el rizado derecho } que salta el cursor hacia abajo hasta el siguiente límite de párrafo; en otras palabras, esto mueve el cursor a la siguiente línea vacía, que es la línea # 4 en nuestro ejemplo. (Esta es la razón por la cual la línea 4 debe ser una línea vacía; sin espacios en blanco, de lo contrario } no lo considerará un límite).

mw}jdd'wpkJj
   ^

La j baja una línea; Esta es la navegación vi "hjkl" de la vieja escuela. Probablemente también podría usar una flecha hacia abajo aquí, encuentro que "j" es algo más fácil de leer y más fácil de usar (porque las teclas de flecha no siempre están en el mismo lugar entre varias marcas de teclados de computadoras portátiles y de escritorio, pero "hjkl "está garantizado para estar siempre en el lado derecho de la fila de inicio de cualquier teclado QWERTY (lo que ayuda a mi velocidad de escritura)).
De todos modos, en este punto, el cursor está en la línea # 5.

+---------------  
| 1 xxx
| 2 yyy  
| 3 zzz  
| 4   
| 5 kkk   (cursor on line#5)
| 6 qqq  
| 7 ppp  
+---------------  

mw}jdd'wpkJj
    ^^

El dd es el comando de edición "eliminar línea", por lo que elimina la línea actual, que es la línea # 5 con el "kkk". La eliminación de la línea también la coloca en el búfer de pegado predeterminado, que usaremos exploit para traer "kkk" de regreso a donde queremos en la línea # 1, al lado de "xxx".

mw}jdd'wpkJj
      ^^

La secuencia 'w (comilla simple w) salta el cursor de nuevo a nuestro marcador para "w", que coloca el cursor en la línea # 1.

mw}jdd'wpkJj
        ^

La "p" en minúscula PONE el búfer predeterminado actual (con "kkk", como recordará) después del cursor. Dado que el búfer contiene lo que solía ser la línea # 5, nuestro archivo ahora se ve brevemente así:

+---------------
| 1 xxx
| 2 kkk    (cursor on line#2, after the freshly restored "kkk")
| 3 yyy
| 4 zzz
| 5 
| 6 qqq
| 7 ppp
+---------------

Observe cómo "kkk" se ha convertido en la línea # 2. (No puedo ilustrar fácilmente dónde va el cursor allí ... realmente debería estar al comienzo de la línea # 2).
Estamos cerca pero aún no estamos allí ...

mw}jdd'wpkJj
         ^^

La minúscula k salta el cursor hasta la línea n. ° 1 (navegación "hjkl" nuevamente), y la J mayúscula une la siguiente línea a la línea actual, haciendo que nuestro archivo se vea así (el cursor todavía está en la línea n. ° 1, entre las x y las k):

+---------------
| 1 xxx kkk    (cursor on line #1, between 'xxx' and 'kkk')
| 2 yyy
| 3 zzz
| 4 
| 5 qqq
| 6 ppp
+---------------


mw}jdd'wpkJj
           ^

La última j es la navegación "hjkl" una vez más, que mueve el cursor hacia abajo a la línea # 2, que es útil porque esa es la siguiente línea a la que queremos aplicar q .
De todos modos, se verá así:

+---------------
| 1 xxx kkk
| 2 yyy       (cursor on #2)
| 3 zzz
| 4 
| 5 qqq
| 6 ppp
+---------------

Si presiona "q" nuevamente y se verá así (tenga en cuenta que el cursor está en la línea # 3).

+---------------
| 1 xxx kkk
| 2 yyy qqq
| 3 zzz        (cursor on #3)
| 4 
| 5 ppp
+---------------

Enjuague y repita según sea necesario. Me resulta útil para listas más largas porque me permite (bastante) sin dolor construir columnas.

Aquí hay un ejemplo más largo. Agregar una línea en blanco en la fila # 7 hace que "ggg" se apile primero en la siguiente columna. Después de bajar a "lll", vuelva a colocar el cursor en la línea n. ° 1 (a la izquierda, {funciona bien para eso) y continúe con "mmm". Si decide que no le gusta la forma en que se está organizando, mantenga presionado u (deshacer) por un momento y modifique donde está la línea "límite" y luego comience nuevamente.

Esta es una de esas cosas que funciona mucho más fácilmente de lo que se necesita esfuerzo para explicar. Si bien no creo que lo use para unir miles de filas, lo encuentro útil para docenas y ocasionalmente cientos.

+----------:---------------------------
|   before : after
+----------:---------------------------
|  1 aaa   :  1 aaa ggg mmm sss yyy
|  2 bbb   :  2 bbb hhh nnn ttt zzz
|  3 ccc   :  3 ccc iii ooo uuu
|  4 ddd   :  4 ddd jjj ppp vvv
|  5 eee   :  5 eee kkk qqq www
|  6 fff   :  6 fff lll rrr xxx
|  7       :-------------------------
|  8 ggg 
|  9 hhh 
| 10 iii 
| 11 jjj 
| 12 kkk 
| 13 lll 
| 14 mmm 
| 15 nnn 
| 16 ooo 
| 17 ppp 
| 18 qqq 
| 19 rrr 
| 20 sss 
| 21 ttt 
| 22 uuu 
| 23 vvv 
| 24 www 
| 25 xxx 
| 26 yyy 
| 27 zzz
+----------

¿Qué pasa con el personaje extra espacial?
Parte del comportamiento del comando Unir es que coloca un espacio entre las líneas que une.
Si no desea un espacio entre "xxx kkk", puede
agregar un comando de eliminación (x) a la cadena:

simple join (space char):  :map q mw}jdd'wpkJj
join + x (kills space):    :map q mw}jdd'wpkJxj
join w/comma:              :map q mw}jdd'wpkJR,^[j

La "unión + x" mata el espacio usando la x justo después de unir las dos líneas. x en modo Navegación elimina cualquier carácter en el que se encuentre el cursor, que en este caso era el carácter de espacio ofensivo.

La "unión con coma" reemplaza el espacio con una coma. Eso es casi lo mismo, pero veremos la última parte, que es un poco diferente del ejemplo anterior.

:map q mw}jdd'wpkJR,^[j
                  ^

La R nos coloca en el modo Edición (específicamente el modo Reemplazar, que sobrescribirá cualquier carácter con lo que escribimos).

 :map q mw}jdd'wpkJR,^[j
                    ^

El , literalmente tipos una coma, que es sobrescribe el espacio infractor en ese punto.

 :map q mw}jdd'wpkJR,^[j
                     ^^

Y luego ^ [ señala un carácter de Escape, que sale del modo Edición y nos vuelve a poner en modo Navegación.
Ahora estamos listos para que la j final nos lleve a la siguiente línea.

Para mapear un personaje de escape, debe presionar ^ Q (windows) o ^ V (linux y unix) y luego presionar la tecla Esc (si no lo hace, el personaje Esc abortará el comando y su izquierda se preguntará por qué su mapa posiblemente complejo definición simplemente desapareció). Aquí está la secuencia que tendría que escribir para ingresarla a Vim en Windows:

:map q mw}jdd'wpkJR,<Ctr-Q><Esc>j

Entonces. Probablemente hay docenas de formas de hacer este tipo de cosas, Vim.
Cuando los delimitadores de "campo" importan, generalmente pongo una secuencia única simple al final de cada línea con búsqueda y reemplazo global, adelante y unir las columnas de la manera que quiero y luego reemplazar todo para obtener los separadores específicos que quiero .

De todos modos, este es solo un ejemplo. Espero que lo hayas encontrado interesante.

netdog
fuente