How do I reverse selected lines order in Vim?
Solution 1
To reverse all the lines in a file,
:g/^/m0
For an explanation see
:help 12.4
which also shows how to reverse just a range of lines.
Solution 2
Select the desired lines, hit !
, and in the resulting prompt pipe the lines through tac
a la :'<,'>!tac
. See man tac
for more details.
Solution 3
On Mac OS X, tac
does not exist, but you can use tail -r
to the same effect:
:%!tail -r
This also works nicely for visual mode:
:'<,'>!tail -r
Excerpt from tail(1)
's manpage:
The -r option causes the input to be displayed in reverse order, by line. Additionally, this option changes the meaning of the -b, -c and -n options. When the -r option is specified, these options specify the number of bytes, lines or 512-byte blocks to display, instead of the bytes, lines or blocks from the beginning or end of the input from which to begin the display. The default for the -r option is to display all of the input.
Solution 4
For those more comfortable with Visual mode:
1. Identify the line number above the selection you want flipped using :set nu
.
2. Shift-V
to highlight selection you want flipped (visual mode).
3. :g/^/m <Line number from step 1>
.
Note that in visual mode it will automatically show up as
:'<,'>g/^/m <Line number>
when you type in the command from 3.
This command works by moving the selection one line at a time into the line number that you give it. When the second item gets pushed into the line number given, it pushes the first down to line number + 1. Then the third pushes the first and second down and so on until the entire list has been pushed into the single line number resulting in a reverse ordered list.
Solution 5
A command :Rev[erse]
and optional mappings for your vimrc
, so you don't have to remember and perform the non-obvious steps of this recipe:
" 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>
(:xmap
maps for Visual but not Select mode, as :help mapmode-x
advises for mapping printable characters.)
(Based on: http://tech.groups.yahoo.com/group/vim/message/34305 )
Related videos on Youtube
Comments
-
Jichao over 1 year
For example, if I have four lines as follows:
the first line
the second line
the third line
the fourth lineI want to reverse them to
the fourth line
the third line
the second line
the first lineHow could I do this in Vim?
-
Palec over 9 yearsDuplicate on Stack Overflow: How to flip a visual selection in vim?
-
Palec over 9 yearsRelated: Reverse all lines @ Vim Wikia
-
qeatzy over 6 years
:command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1
vi.stackexchange.com/a/2107/10254
-
-
Brent Faust over 10 yearsGreat tip on the exact help section! To summarize: 1. set a marker at the last line you want reverse (I name the marker 'a' using
ma
), 2. move cursor to the first line of the block, 3. type:'a,.g/^/m 'a
-
Brent Faust over 10 yearsExcellent! So to provide 'tac' under OS X:
alias tac='tail -r'
-
Andrew Marshall about 10 yearsYou can also
brew install coreutils
and usegtac
. -
wisbucky almost 10 yearsTo select the lines, use
shift+v
to enter visual line mode, thenj
to add lines to the selection. -
Palec over 7 yearsYou can use the
'<
instead of entering the line number manually. Just start the selection one line earlier and execute:'<,'>g/^/m'<
. -
Eliot over 7 yearsThis should be the accepted answer IMO. Most generally useful and I don't have to remember
:'<,'>g/^/m'<
:) -
Aaron Thoma over 7 years@Eliot, thanks! :) (I added a bit of 'bonus content'. ;) )
-
SergioAraujo about 6 yearsHow can I say selection start -1 in this case? Because the move starts at this point.
-
Aaron Thoma about 6 years@SergioAraujo: Is something like
:-1,+1Rev
what you are looking for? Know that you can visually select the range you want to reverse, e.g.:V7j:Rev
. If that doesn’t answer your question, I haven’t understood it, so you’d need to elaborate or rephrase it for me. -
Aaron Thoma about 6 yearsYou can leave the current line’s number implicit: With the cursor on your range’s first line, you can shorten to
:,6g/^/m2
; or when on the range’s last line::3,g/^/m2
; and:3,6g/^/m2
works from anywhere in the file. -
dylnmc about 6 yearsI can confirm that this works in windows with
gvim
, as well! Otherwise, you have to use absolute line numbers (maybe you can use relative, but you have to be careful) with the:g/^/m0
(which is also really hard to remember) ... So, essentially, tac should be with vim no matter what platform you're on, BUT it's not 100% vimscript, BUT who cares :P -
studog over 5 yearstac isn't fully-native vim handling, but, the 'm'ove command takes a line number and that's not always reasonable. I often use a mark as part of a range, so
:.,'a!tac
works with minimal effort. -
Charlie Dalsass almost 5 yearsGenius. Never thought of using ! commands for this type of visual line manipulation.
-
nilon over 4 yearsAfter using
shift+v
, you can use}
to reach up to the next paragraph, or empty vertical space. Also,man tac: concatenate and print files in reverse
. -
young_souvlaki about 2 years
-
young_souvlaki about 2 yearsThis is so money!!!