5

We have two separate files:

f1.txt

17.0,
155.7,
1123,9,

and

f2.txt

1
2
3

After opening files vertically with vim -O ~/f1.txt ~/f2.txt

How to obtain?

17.0,1
155.7,2
1123,9,3

which is the equivalent of paste -d '' f1.txt f2.txt in bash


I tried all I could but in the end I got:

17.0,1
155.72,
1123,39,

So the column was pasted vertically but not appended to the end of the existing line.

2
  • 2
    I'm guessing you won't accept :!paste -d '' f1.txt f2.txt as an answer? ;)
    – Rich
    Aug 18, 2016 at 9:27
  • 2
    :set virtualedit=all, paste the column somewhere to the right, then :%s/,\s*//. :) Aug 18, 2016 at 10:42

4 Answers 4

9

I have answered a similar question here: https://stackoverflow.com/a/20050503/164835 But that question is not exactly same as this one, so I answer here once again:

in File1 do:

  • :%right
  • 0<ctrl-v>G$ -> column select all
  • y -> yank

in File2 do:

  • P -> paste
  • :%left

Done!

It is pure vim solution, and goes pretty easy, looks like:

enter image description here

1
  • 1
    Using :left and :right is pretty clever actually!
    – statox
    Aug 19, 2016 at 15:33
3

I'd rather use the paste command line tool, if you are using Linux/BSD/OSX:

paste -d '' f1.txt f2.txt

should do what you want. You can also read the result into the current vi buffer with :r!paste -d '' f1.txt f2.txt.

Vim's block-visual mode can be very useful but for CSV-ish data, I'd recommend paste or chrisbra/csv.vim.

2
  • It would be better if the answer is specific to vim
    – SibiCoder
    Aug 18, 2016 at 9:51
  • 4
    @SibiCoder Please define "better". Aug 18, 2016 at 10:43
2

Using a macro:

qq<c-w><c-w>y$<c-w><c-w>$p+<c-w><c-w>+<c-w><c-w>q2@q
  1. qq: Start recording a macro,
  2. <c-w><c-w>: Switch to second window,
  3. y$: yank the contents of the line,
  4. <c-w><c-w>: Switch back to first window,
  5. $p: Paste at the end of the line,
  6. +<c-w><c-w>+<c-w><c-w>: Move down a line in both windows,
  7. q: End the recording,
  8. 2@q: Replay the recording twice.
2

And here is another solution, probably not the most efficient one or the cleaner one but I had some time to make some vimscript:

function! PasteAtEndOfLine()
    " Check that the selection is blockwise
    if ( getregtype('"')[0] != '' )
        echo "not blockwise"
        return
    endif

    " Get the selection and split it on new lines
    let regcontent = getreg('"')
    let lines = split(regcontent, '\n')

    " Save the cursor position and the current line
    let save_cursor = getpos('.')
    let line_number = save_cursor[1]

    " For each line add the content of the register at the end
    " And go to next line
    for line in lines
        execute "normal A" . line
        let line_number += 1
        call setpos('.', [0, line_number, 0, 0])
    endfor

    " Restore the initial position
    call setpos('.', save_cursor)
endfunction

To use it you should:

  • Visually select block wise the lines you want to paste from f2.txt: ctrl+vG
  • Yank the text to the unnamed register: y
  • Go to the first line of f1.txt
  • Call the function: :call PasteAtEndOfLine()
  • You're done
1
  • Same idea, but using sub-replace-special :s\=: :'<,'>s/$/\=getreg('"',1,1)[line("'<")-line('.')] Feb 8, 2022 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.