salir para modo linea insertar inicio guardar documento como comando cerrar borrar vim

para - vim borrar linea



Fusionar mĂșltiples lĂ­neas(dos bloques) en Vim (9)

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


Así es como lo haría (con el cursor en la primera línea):

qama:5<CR>y$''a$p:5<CR>dd''ajq3@a

Necesitas saber dos cosas:

  • El número de línea en el que comienza la primera línea del segundo grupo (5 en mi caso), y
  • el número de líneas en cada grupo (3 en mi ejemplo).

Esto es lo que está pasando:

  • qa registra todo hasta el siguiente q en un "búfer" en a .
  • ma crea una marca en la linea actual
  • :5<CR> va al siguiente grupo.
  • y$ tira el resto de la línea.
  • ''a vuelve a la marca, establecido anteriormente.
  • $p pastas al final de la línea.
  • :5<CR> regresa a la primera línea del segundo grupo.
  • dd 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)

Ciertamente, puedes hacer todo esto con una sola copia / pegado (utilizando la selección en modo bloque), pero supongo que no es lo que quieres.

Si quieres hacer esto con solo comandos Ex

:5,8del | let l=split(@") | 1,4s/$//=remove(l,0)/

se transformará

work it make it do it makes us harder better faster stronger ~

dentro

work it harder make it better do it faster makes us stronger ~

ACTUALIZACIÓN: Una respuesta con esta gran cantidad de upvotes merece una explicación más completa.

En Vim, puede utilizar el carácter de canalización ( | ) para encadenar varios comandos Ex, por lo que lo anterior es equivalente a

:5,8del :let l=split(@") :1,4s/$//=remove(l,0)/

Muchos comandos Ex aceptan un rango de líneas como argumento de prefijo: en el caso anterior, el 5,8 antes del del y el 1,4 antes del s/// especifican en qué líneas operan los comandos.

borra las líneas dadas. Puede tomar un argumento de registro, pero cuando no se da uno, se vuelcan las líneas al registro sin nombre, @" , al igual que la eliminación en el modo normal, let l=split(@") luego divide las líneas eliminadas en una lista , utilizando el delimitador predeterminado: espacios en blanco. Para trabajar correctamente en la entrada que tenía espacios en blanco en las líneas eliminadas, como:

more than hour our never ever after work is over ~

necesitaríamos especificar un delimitador diferente, para evitar que "trabajo es" se divida 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ón remove(l,0) . remove(l,0) altera la lista l , borrando 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 usando remove(l,-1) .


Como se mencionó en otra parte, la selección de bloques es el camino a seguir. Pero también puedes 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 utilidad de paste fue creada para manejar este tipo de fusión de líneas.

PASTE(1) BSD General Commands Manual PASTE(1) NAME paste -- merge corresponding or subsequent lines of files SYNOPSIS paste [-s] [-d list] file ... DESCRIPTION The paste utility concatenates the corresponding lines of the given input files, replacing all but the last file''s newline characters with a single tab character, and writes the resulting lines to standard output. If end-of-file is reached on an input file while other input files still contain data, the file is treated as if it were an endless source of empty lines.


Los datos de muestra son los mismos que los de rampion.

:1,4s/$//=getline(line(''.'')+4)/ | 5,8d


No creo que lo haga demasiado complicado. Yo solo pondría virtualedit en
( :set virtualedit=all )
Seleccione el bloque 123 y todo a continuación.
Ponlo después de la primera columna:

abc 123 def 45 ... ...

y eliminar el espacio múltiple entre 1 espacio:

:%s//s/{2,}/ /g


Para unir bloques de línea, tienes que hacer los siguientes pasos:

  1. Ir a la tercera línea: jj
  2. Entrar en el modo de bloqueo visual: CTRL-v
  3. Fije el cursor al final de la línea (importante para líneas de diferente longitud): $
  4. Ir al final: CTRL-END
  5. Cortar el bloque: x
  6. Ir al final de la primera línea: kk$
  7. Pega el bloque aquí: p

El movimiento no es el mejor (no soy un experto), pero funciona como usted quería. Espero que haya una versión más corta de la misma.

Estos son los requisitos previos para que esta técnica funcione bien:

  • Todas las líneas del bloque de inicio (en el ejemplo de la pregunta abc y def ) tienen la misma longitud XOR
  • la primera línea del bloque de inicio es la más larga, y no te importan los espacios adicionales que se encuentran en el medio) XOR
  • La primera línea del bloque inicial no es la más larga, y hay espacios adicionales hasta el final.

Puede haber muchas formas de lograr esto. Combinaré dos bloques de texto usando cualquiera de los dos métodos siguientes.

suponga que el primer bloque está en la línea 1 y el segundo bloque comienza desde la línea 10 con la posición inicial del cursor en la línea número 1.

(/ n significa presionar la tecla enter.)

1. abc def ghi 10. 123 456 789

con una macro usando los comandos: copiar, pegar y unir.

qaqqa: + 9y / npkJjq2 @ a10G3dd

con una macro usando los comandos, mueva una línea al número de la línea n y únase.

qcqqc: 10m. / nkJjq2 @ c


Se puede obtener un comando Ex elegante y conciso para resolver el problema combinando los comandos :global :move y :join . Suponiendo que el primer bloque de líneas comienza en la primera línea del búfer, y que el cursor está ubicado en la línea inmediatamente anterior a la primera línea del segundo bloque, el comando es el siguiente.

:1,g/^/''''+m.|-j!

Para una explicación detallada de la técnica utilizada, vea la answer que di a la pregunta "¿ Vim paste -d '''' comportamiento fuera de la caja? ".


Yo usaría repeticiones complejas :)

Dado este:

aaa bbb ccc AAA BBB CCC

Con el cursor en la primera "a" en la primera línea, presione lo siguiente:

qq}jdd''''$pkJj0q

y luego presione @q (y luego puede usar @@ ) tantas veces como sea necesario.

Deberías terminar con:

aaaAAA bbbBBB cccCCC

(Más una nueva línea).