Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Let's suppose I have a file containing:

xxx
yyy
zzz

and another file:

kkk
qqq
ppp

I want to obtain:

xxxkkk
yyyqqq
zzzppp

Is that possible in Vim with some command? (I've tried using VISUAL BLOCK but with no success).

In my particular case I have two big files with many lines to paste so the answer could also be some shell command but i would like to know if there's a way to do it even within the same file.

share|improve this question

3 Answers 3

up vote 12 down vote accepted

From the command line, you could try

paste -d '\0' file1 file2 > file3

That does exactly what you want.

Visual Block mode in vim is also perfectly suited for this task. Are you sure you did it correctly? You should

  • Go to visual block mode
  • Select text and press y for yanking
  • Go to the other file, on the upper left corner of the to be paste data (last x) and press p.
share|improve this answer
    
I was pasting in Visual Block... that's exactly what i wanted to do. Thank you. –  Fabio F. Jun 5 at 13:32
1  
At least with GNU Coreutils, paste -d '' ... also works. Interestingly, the coreutils manpage and info pages seem to not document '\0', even though its specified in the Single Unix Spec. –  derobert Jun 5 at 16:06

You can do directly when editting file1. Type : to switch to command mode in vim. Then type:

%!paste -d '' - file2
share|improve this answer

Here's a way to do it within the same file using just Vim.

It involves some key-mapping. I came up with this once when I wanted to arrange several lists into table-like structures in simple text.

This relies on the } key (right curly-brace) to skip paragraph boundaries. (The braces are mirrored, btw: { skips towards the top of file and } towards the end.)

So... suppose you have a data file like this (this supposes that line#'s are turned on with :set nu):

+---------------  
| 1 xxx    (cursor on line#1)  
| 2 yyy  
| 3 zzz  
| 4   
| 5 kkk  
| 6 qqq  
| 7 ppp  
+---------------  

It is important that line #4 is an empty line (no whitespace), I'll explain why in a moment.

Execute the following map command:
:map q mw}jdd'wpkJj

This binds the "q" key to a 12 character program, which I'll break down in some detail below.

When you hit "q" it will execute that program; note that your cursor, which started on line #1 is now on the next line, ready to hit "q" again. You may have noticed there is a space character between "xxx kkk"; if you don't want that then see "What About The Extra Space Character?" below, near the end.

+---------------
| 1 xxx kkk
| 2 yyy   (cursor on line #2)
| 3 zzz
| 4 
| 5 qqq
| 6 qqq
| ~
+---------------

Here's a breakdown of the mapping:

   :map q mw}jdd'wpkJj
   ^

The colon gets you into command mode so we can issue the "map" command.

   :map q mw}jdd'wpkJj
    ^^^^^

map q binds q with the following character sequence. Note that "q" is just my usual "map to" key; you can use other keys. By default lowercase q is mapped to start macro recording; since I rarely (never?) use that I find "q" more helpful for one-off utility macros. You could also use uppercase Q (e.g. map Q) or a fnct key or so on.

Now whenever you press "q" (in navigation mode), vim will execute this series of keystrokes:

   mw}jdd'wpkJj

Which of course looks like total gibberish, so I'll break it down action-by-action (with ^^'s below) to make it easier to follow what is happening.

mw}jdd'wpkJj
^^

The mw MARKs a named location, the name here is 'w'. I use 'w' by default (I think of that as my 'w'orking location. Any named location, from a-z would work, so long as you're consistent.
The 'w' will show up again in a bit when we want to return the cursor to this line.

mw}jdd'wpkJj
  ^

Here we have the right-curly } which jumps the cursor down to the next paragraph boundary; in other words, this moves the cursor to the next empty line, which is line# 4 in our example. (This is why line #4 should be an empty line; no whitespace, otherwise } won't consider it a boundary.)

mw}jdd'wpkJj
   ^

The j goes down one line; this is the old-school vi "hjkl" navigation. You could probably use a down-arrow here as well, I find "j" somewhat easier to read, and easier to use (because arrow keys aren't always in the same place between various brands of laptop and desktop keyboards, but "hjkl" is Guaranteed to always be on right hand side of any QWERTY keyboard's home-row (which helps my typing speed)).
Anyway, at this point, the cursor is on line# 5.

+---------------  
| 1 xxx
| 2 yyy  
| 3 zzz  
| 4   
| 5 kkk   (cursor on line#5)
| 6 qqq  
| 7 ppp  
+---------------  

mw}jdd'wpkJj
    ^^

The dd is the "delete line" edit command, so it deletes the current line, which is line#5 with the "kkk" on it. Deleting the line also puts it in the default paste buffer, which we'll use exploit to bring "kkk" back to where we want it on line #1, next to "xxx".

mw}jdd'wpkJj
      ^^

The 'w (single-quote w) sequence jumps the cursor back to our bookmark for "w", which puts the cursor on line#1.

mw}jdd'wpkJj
        ^

The lowercase "p" PUTS the current default buffer (with "kkk", as you'll recall) after the cursor. Since the buffer contains what used to be line#5, our file briefly looks like this now:

+---------------
| 1 xxx
| 2 kkk    (cursor on line#2, after the freshly restored "kkk")
| 3 yyy
| 4 zzz
| 5 
| 6 qqq
| 7 ppp
+---------------

Note how "kkk" has become line#2. (I can't easily illustrate where the cursor goes there... it should really be at the beginning of line#2).
We're close but not quite there yet...

mw}jdd'wpkJj
         ^^

The lower-case k hops the cursor up to line#1 ("hjkl" navigation again), and the uppercase J joins the next line onto the current line, making our file look like this (cursor is still on line #1, between the x's & the k's):

+---------------
| 1 xxx kkk    (cursor on line #1, between 'xxx' and 'kkk')
| 2 yyy
| 3 zzz
| 4 
| 5 qqq
| 6 ppp
+---------------


mw}jdd'wpkJj
           ^

The last j is "hjkl" navigation once more, which moves the cursor down to line#2 which is handy because that is the next line we want to apply q to.
Anyway way, it will look like this:

+---------------
| 1 xxx kkk
| 2 yyy       (cursor on #2)
| 3 zzz
| 4 
| 5 qqq
| 6 ppp
+---------------

If you hit "q" again and it will look like this (note the curser is on line#3).

+---------------
| 1 xxx kkk
| 2 yyy qqq
| 3 zzz        (cursor on #3)
| 4 
| 5 ppp
+---------------

Rinse and repeat as necessary. I find this handy for longer lists because it lets me (fairly) painlessly build up columns.

Here's a longer example. Adding a blank line at row #7 causes "ggg" to stack first in the next column. After getting down to "lll", jump your cursor back up to line #1 ( left curly, {, works well for that) and keep going with "mmm". If you decide you don't quite like the way it is arranging, hold down on u (undo) for a bit and tweak where you "boundary" line is then start over.

This is one of those things that works much easier than it takes effort to explain. While I don't think I'd use it for joining thousands of rows I find it handy for dozens and occasionally hundreds.

+----------:---------------------------
|   before : after
+----------:---------------------------
|  1 aaa   :  1 aaa ggg mmm sss yyy
|  2 bbb   :  2 bbb hhh nnn ttt zzz
|  3 ccc   :  3 ccc iii ooo uuu
|  4 ddd   :  4 ddd jjj ppp vvv
|  5 eee   :  5 eee kkk qqq www
|  6 fff   :  6 fff lll rrr xxx
|  7       :-------------------------
|  8 ggg 
|  9 hhh 
| 10 iii 
| 11 jjj 
| 12 kkk 
| 13 lll 
| 14 mmm 
| 15 nnn 
| 16 ooo 
| 17 ppp 
| 18 qqq 
| 19 rrr 
| 20 sss 
| 21 ttt 
| 22 uuu 
| 23 vvv 
| 24 www 
| 25 xxx 
| 26 yyy 
| 27 zzz
+----------

What About The Extra Space Character?
Part of the Join command's behaviour is that it puts a space between lines that it joins.
If you don't want a space between "xxx kkk" you can
add a delete-command (x) to the string:

simple join (space char):  :map q mw}jdd'wpkJj
join + x (kills space):    :map q mw}jdd'wpkJxj
join w/comma:              :map q mw}jdd'wpkJR,^[j

The "join + x" kills the space by using the x right after we join the two lines together. x in Navigation mode deletes whatever character the cursor happens to be on, which in this case was the offending space character.

The "join w/comma" replaces the space with a comma. That is mostly the same but we'll step through the last part which is just a bit different from the previous example.

:map q mw}jdd'wpkJR,^[j
                  ^

The R places us into Edit mode (specifically Replace mode, which will overwrite any characters with what we type).

 :map q mw}jdd'wpkJR,^[j
                    ^

The , literally types a comma, which is overwrites the offending space at that point.

 :map q mw}jdd'wpkJR,^[j
                     ^^

And then ^[ signals an Escape character, which leaves Edit mode and puts us back in Navigation mode.
Now we're ready for the final j to take us down to the next line.

To map an escape character you need to hit ^Q (windows) or ^V (linux & unix) then press the Esc key (if you don't, the Esc character will abort the command and your left wondering why your possibly complex map definition just vanished). Here's the sequence you'd have to type to get it into Vim on Windows:

:map q mw}jdd'wpkJR,<Ctr-Q><Esc>j

So. There are probably dozens of ways to do this sort of thing Vim.
When "field" delimiters matter, I usually put a simple unique sequence at the end of every line with global search and replace, go ahead and join up the columns the way I want and then replace-all to get the specific separator's that I want.

Anyway, this is just one example. I hope you found it interesting.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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