Come posso invertire l'ordine delle linee selezionate in Vim?


95

Ad esempio, se ho quattro righe come segue:

la prima riga
la seconda riga
la terza riga
la quarta riga

Voglio invertirli

la quarta riga
la terza riga
la seconda riga
la prima riga

Come potrei farlo in Vim?




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

Risposte:


87

Per invertire tutte le righe in un file,

:g/^/m0

Per una spiegazione vedi

:help 12.4

che mostra anche come invertire solo un intervallo di linee.


12
Ottimo consiglio sull'esatta sezione di aiuto! Riassumendo: 1. posiziona un marker sull'ultima riga che vuoi invertire (io chiamo il marker 'a' usando ma), 2. sposta il cursore sulla prima riga del blocco, 3. digita:'a,.g/^/m 'a
Brent Faust il

70

Seleziona le linee desiderate, premi !e nel prompt risultante reindirizza le linee attraverso tacun la :'<,'>!tac. Vedi man tacper maggiori dettagli.


4
Per selezionare le linee, utilizzare shift+vper accedere alla modalità linea visiva, quindi jper aggiungere linee alla selezione.
Wisbucky

Posso confermare che funziona anche con Windows gvim! Altrimenti, devi usare numeri di riga assoluti (forse puoi usare il relativo, ma devi stare attento) con il :g/^/m0(che è anche molto difficile da ricordare) ... Quindi, in sostanza, tac dovrebbe essere con vim indipendentemente dalla piattaforma sei su, MA non è vimscript al 100%, MA a chi importa: P
dylnmc

tac non è una gestione vim completamente nativa, ma il comando 'm'ove accetta un numero di riga e questo non è sempre ragionevole. Uso spesso un marchio come parte di un intervallo, quindi :.,'a!tacfunziona con il minimo sforzo.
Studog,

Dopo l'uso shift+v, è possibile utilizzare }per raggiungere il paragrafo successivo o per svuotare lo spazio verticale. Inoltre, man tac: concatenate and print files in reverse.
nilon,

33

Su Mac OS X, tacnon esiste, ma puoi utilizzare tail -rcon lo stesso effetto:

:%!tail -r

Questo funziona bene anche per la modalità visiva:

:'<,'>!tail -r

Estratto dalla tail(1)manpage di:

L'opzione -r fa sì che l'ingresso venga visualizzato in ordine inverso, per riga. Inoltre, questa opzione modifica il significato delle opzioni -b, -c e -n. Quando viene specificata l'opzione -r, queste opzioni specificano il numero di byte, linee o blocchi da 512 byte da visualizzare, anziché byte, linee o blocchi dall'inizio o dalla fine dell'ingresso da cui iniziare la visualizzazione. L'impostazione predefinita per l'opzione -r è di visualizzare tutto l'input.


3
Eccellente! Quindi per fornire 'tac' sotto OS X:alias tac='tail -r'
Brent Faust,

4
Puoi anche brew install coreutilse usare gtac.
Andrew Marshall,

1
Genio. Non ho mai pensato di usare! comandi per questo tipo di manipolazione della linea visiva.
Charlie Dalsass,

3

Per chi è più a suo agio con la modalità Visual:
1. Identifica il numero di riga sopra la selezione che desideri invertire :set nu.
2. Shift-Vper evidenziare la selezione che si desidera invertire (modalità visiva).
3 :g/^/m <Line number from step 1>.

Si noti che in modalità visiva apparirà automaticamente come :'<,'>g/^/m <Line number>quando si digita il comando da 3.

Questo comando funziona spostando la selezione di una riga alla volta nel numero di riga assegnato. Quando il secondo elemento viene inserito nel numero di riga indicato, spinge il primo verso il basso fino al numero di riga + 1. Quindi il terzo spinge il primo e il secondo verso il basso e così via fino a quando l'intero elenco non viene inserito nel numero di singola riga risultante in un lista ordinata inversa.


4
È possibile utilizzare '<invece di immettere manualmente il numero di riga. Basta avviare la selezione una riga prima ed eseguire :'<,'>g/^/m'<.
Palec,

3

Un comando :Rev[erse]e mappature opzionali per il tuo vimrc, quindi non devi ricordare ed eseguire i passaggi non ovvi di questa ricetta:

" 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>

( :xmapmappe per la modalità Visual ma non Select, come :help mapmode-xconsigliato per la mappatura dei caratteri stampabili.)

(Basato su: http://tech.groups.yahoo.com/group/vim/message/34305 )


Questa dovrebbe essere la risposta accettata IMO. Più generalmente utile e non devo ricordare :'<,'>g/^/m'<:)
Eliot

1
@Eliot, grazie! :) (Ho aggiunto un po 'di' bonus content '.;))
Aaron Thoma il

Come posso dire che la selezione inizia -1 in questo caso? Perché la mossa inizia a questo punto.
SergioAraujo,

@SergioAraujo: è qualcosa di simile a :-1,+1Revquello che stai cercando? Sappiate che è possibile selezionare visivamente l'intervallo si vuole invertire, per esempio: V7j:Rev. Se questo non risponde alla tua domanda, non l'ho capito, quindi dovrai elaborarlo o riformularlo per me.
Aaron Thoma,

1

Supponiamo che tu sia alla riga 3, quindi abbiamo un intervallo da 3 a 6. Basta digitare.

:3,6g/^/m2

1
Puoi lasciare implicito il numero della riga corrente: con il cursore sulla prima riga del tuo intervallo, puoi accorciare :,6g/^/m2; o quando in ultima linea della gamma: :3,g/^/m2; e :3,6g/^/m2funziona da qualsiasi parte del file.
Aaron Thoma,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.