Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Put a selection of yanked lines at the end of other lines vim

Tags:

vim

How can I put a selection of yanked lines at the end of other lines?

BEFORE:

11 
1 
2 
3 
10 

0.0
0.045
0.09
0

AFTER:

11 
1 0.0
2 0.045
3 0.09
10 0
like image 377
EarthIsHome Avatar asked Nov 16 '25 18:11

EarthIsHome


2 Answers

To make a block selection until the line-end, even for an unmatched number of columns, first select vertically the first column in all lines and then press $.

So in your case, move the cursor to the first column of 0.0, press ctrl-v, move the cursor down to the last line, press $ and you have the block selection. Now you can cut it with d and paste it in the second line.

Edit: Since you put this 10 there, the pasting part gets a bit more complicated. I would first past the block in the right-most column that doesn't interfere with the other columns. So go to the second line, append two blanks after the 1 and then paste the block. The result will look like this:

11
1  0.0
2  0.045
3  0.09
10 0

Now you need to remove the duplicated blanks in all the lines (if they disturb you). In a simple example like this, you can do it just with another block selection. In more complicated examples you might do it with a search/replace pattern.

like image 75
Georg P. Avatar answered Nov 19 '25 11:11

Georg P.


For this specific case you could also use :g and :m to reorder the lines and join them. With the cursor at the first line, do a }dd to delete the empty line. Cursor should be at the line with 0.0. Now do a simple:

:,$g/./2m-1|j

Vim Demo

This works with :g acting as a sort of iterator over the lines. The :g command selects lines within a range matching a certain pattern and runs a command on such matched lines in the form :[range]g{pattern}{command}. Breaking it into smaller parts we have:

  • ,$ this range is a short form of .,$, meaning from current line to the end of the file. That's why the cursor position is important.
  • /./ match lines containing any character, effectively a placeholder to say match every line.
  • 2m-1|j the "tricky" part, composed of two commands:
    • 2m-1 the move command, in the form [range]m{address}. Moves lines from range to below address. As utilized it means move the second line to address -1 which itself is another piece of "trickery". -1 is a short form of .-1 which means current line position (.) minus one. At this point, the cursor is moved upwards to sit on the line just moved.
    • j join command, joins the current line to the next one with a space in between.

You can simulate what happens step by step by running :2m-1 and then :j yourself on each line starting from the line with 0.0. Again, the :g here works just as an iterator for these commands over those last 4 lines.

Starting with (* represents cursor position):

  11
  1
  2
  3
  10
* 0.0
  0.045
  0.09
  0

Running :2 move .-1 transforms it into:

  11
  2
  3
  10
* 1
  0.0
  0.045
  0.09
  0 

Then :join

  11
  2
  3
  10
* 1 0.0
  0.045
  0.09
  0

Move to the next line and repeat.

like image 30
sidyll Avatar answered Nov 19 '25 10:11

sidyll