¿Cómo invierto el orden de las líneas seleccionadas en Vim?

94

Por ejemplo, si tengo cuatro líneas de la siguiente manera:

la primera línea
la segunda línea
la tercera línea
la cuarta línea

Quiero revertirlos a

la cuarta línea
la tercera línea
la segunda línea
la primera línea

¿Cómo podría hacer esto en Vim?

Jichao
fuente
1
:command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1 vi.stackexchange.com/a/2107/10254
qeatzy

Respuestas:

86

Para invertir todas las líneas en un archivo,

:g/^/m0

Para una explicación ver

:help 12.4

que también muestra cómo invertir solo un rango de líneas.

garyjohn
fuente
12
Gran consejo sobre la sección de ayuda exacta! Para resumir: 1. establezca un marcador en la última línea que desea revertir (llamo al marcador 'a' usando ma), 2. mueva el cursor a la primera línea del bloque, 3. escriba:'a,.g/^/m 'a
Brent Faust
69

Seleccione las líneas deseadas, presione !, y en el indicador resultante canalice las líneas a través de tacuna :'<,'>!tac. Ver man tacpara más detalles.

Rhys Ulerich
fuente
44
Para seleccionar las líneas, use shift+vpara ingresar al modo de línea visual, luego jpara agregar líneas a la selección.
wisbucky
¡Puedo confirmar que esto también funciona en Windows gvim! De lo contrario, debe usar números de línea absolutos (tal vez puede usar relativo, pero debe tener cuidado) con el :g/^/m0(que también es realmente difícil de recordar) ... Entonces, esencialmente, tac debe estar con vim sin importar qué plataforma estás en, PERO no es 100% vimscript, PERO a quién le importa: P
dylnmc
tac no es un manejo vim completamente nativo, pero el comando 'm'ove toma un número de línea y eso no siempre es razonable. A menudo uso una marca como parte de un rango, por lo que :.,'a!tacfunciona con un mínimo esfuerzo.
studog
Después de usar shift+v, puede usar }para llegar hasta el siguiente párrafo, o vaciar el espacio vertical. Además, man tac: concatenate and print files in reverse.
nilon
33

En Mac OS X, tacno existe, pero puede usarlo tail -rpara el mismo efecto:

:%!tail -r

Esto también funciona bien para el modo visual:

:'<,'>!tail -r

Extracto de tail(1)la página de manual de:

La opción -r hace que la entrada se muestre en orden inverso, por línea. Además, esta opción cambia el significado de las opciones -b, -c y -n. Cuando se especifica la opción -r, estas opciones especifican el número de bytes, líneas o bloques de 512 bytes para mostrar, en lugar de los bytes, líneas o bloques desde el principio o el final de la entrada desde la cual comenzar la visualización. El valor predeterminado para la opción -r es mostrar toda la entrada.

Thomas Perl
fuente
3
¡Excelente! Entonces, para proporcionar 'tac' en OS X:alias tac='tail -r'
Brent Faust
44
También puedes brew install coreutilsy usa gtac.
Andrew Marshall
1
Genio. Nunca pensé en usar! comandos para este tipo de manipulación de línea visual.
Charlie Dalsass
3

Para aquellos que se sienten más cómodos con el modo Visual:
1. Identifique el número de línea sobre la selección que desea voltear usando :set nu.
2. Shift-Vpara resaltar la selección que desea voltear (modo visual).
3 :g/^/m <Line number from step 1>..

Tenga en cuenta que en modo visual se mostrará automáticamente como :'<,'>g/^/m <Line number>cuando escribe el comando de 3.

Este comando funciona moviendo la selección una línea a la vez al número de línea que le da. Cuando el segundo elemento se inserta en el número de línea dado, empuja el primero hacia abajo hasta el número de línea + 1. Luego, el tercero empuja el primero y el segundo hacia abajo y así sucesivamente hasta que toda la lista ha sido empujada al número de línea único, lo que resulta en un lista de orden inverso.

Horta
fuente
44
Puede usar el en '<lugar de ingresar el número de línea manualmente. Simplemente comience la selección una línea antes y ejecute :'<,'>g/^/m'<.
Palec
3

Un comando :Rev[erse]y asignaciones opcionales para su vimrc, para que no tenga que recordar y realizar los pasos no obvios de esta receta:

" Reverse the lines of the whole file or a visually highlighted block.
    " :Rev is a shorter prefix you can use.
    " Adapted from http://tech.groups.yahoo.com/group/vim/message/34305
command! -nargs=0 -bar -range=% Reverse
    \       let save_mark_t = getpos("'t")
    \<bar>      <line2>kt
    \<bar>      exe "<line1>,<line2>g/^/m't"
    \<bar>  call setpos("'t", save_mark_t)

nmap <Leader>r :Reverse<CR>
xmap <Leader>r :Reverse<CR>

( :xmapasigna para el modo Visual pero no para Seleccionar, como se :help mapmode-xrecomienda para asignar caracteres imprimibles).

(Basado en: http://tech.groups.yahoo.com/group/vim/message/34305 )

Aaron Thoma
fuente
Esta debería ser la respuesta aceptada de la OMI. Muy útil en general y no tengo que recordar :'<,'>g/^/m'<:)
Eliot
1
@Eliot, gracias! :) (Agregué un poco de 'contenido extra';))
Aaron Thoma el
¿Cómo puedo decir que la selección comienza -1 en este caso? Porque el movimiento comienza en este punto.
SergioAraujo
@SergioAraujo: ¿Es algo como :-1,+1Revlo que estás buscando? Sepa que usted puede seleccionar visualmente el rango que desea revertir, por ejemplo: V7j:Rev. Si eso no responde a su pregunta, no lo he entendido, por lo que necesitaría elaborarlo o reformularlo para mí.
Aaron Thoma
1

Digamos que está en la línea 3, por lo tanto, tenemos un rango de 3 a 6. Simplemente escriba.

:3,6g/^/m2
SergioAraujo
fuente
1
Puede dejar implícito el número de la línea actual: con el cursor en la primera línea de su rango, puede acortar a :,6g/^/m2; o cuando en la última línea de la gama: :3,g/^/m2; y :3,6g/^/m2funciona desde cualquier parte del archivo.
Aaron Thoma