I would like to copy several lines with line numbers; the text from set number isn't copied. Is there any way to do this?

  • 1
    When Vim runs within tmux (and possibly other tools), you could achieve this by using the copy mode; assuming you have the set numbers on.
    – Rolf
    May 29, 2019 at 6:32

3 Answers 3


You have several alternatives.

  1. Use the TOhtml command to let Vim generate an HTML file, which includes the line numbers, and then copy and paste from that file.

  2. Replace each line by its line number plus its content, so you can copy it with the line number. This can be done by visually selecting the lines, and using the following substitute command:

    :s/^/\=printf("%2d ", line('.'))/ 

    You obviously want to undo this replace after copying using e.g. undo or :s/^\d\+ //

  3. Create your own command to take care of copying the desired text together with the line numbers. Something like this should work:

    fu! s:yank_number(first, last) 
        let start = a:first 
        let l = [] 
        while start <= a:last 
            let l = add(l, printf("%" . len(a:last) . "d %s", start, " " . getline(start))) 
            let start += 1
        return join(l, "\n") . "\n" 
    command! -nargs=0 -range Yank :let @+ = s:yank_number(<line1>, <line2>) 

    Now select your text and enter :Yank, which will copy the range to the +-register (which should correspond to your system's clipboard, if your Vim was compiled with clipboard functionality (:help should output +clipboard, instead of -clipboard).

  4. Use :redir:

    :redir @a 
    :silent! :'<,'>number
    :redir END 


    :redir @a | silent! :'<,'>number | redir END

    to pull the numbered lines into register "a". This can be wrapped into a mapping:

    :vnoremap <f4> :<home>redir @a<bar>silent! <end>number<bar>redir END<cr> 

    assuming you always want to trump the same register. If you use it frequently, you might designate a preferred register such as "n" for "(n)umbered" and then only use it for that purpose. Alternatively, :redir allows you to redirect to other sinks if you prefer.

DISCLAIMER: The above options have been created from the Vim mailing list thread, using:

If you are one of the above authors, and would like to take credit for it, please let me know, and I will delete the question and answer so that you can re-create it.

  • 1
    You can use execute() instead of :redir to not clobber a register: :echo execute("'<,'>#"). I've also found some weird bugs with :redir over the years, and generally try to avoid it. May 15, 2019 at 22:02
  • execute() did not exists back when that question was initially asked May 16, 2019 at 6:35
  • Hi @MartinTournoij .. I use redir to load the clipboard with a command's output pretty often. I don't recall ever having problems. OTOH I've only been doing this for, oh, the last 3 years or so so perhaps there were issues but they've since been fixed. Have you had any problems that you recall in that same rough time frame? (Out of curiosity primarily. Thanks.)
    – B Layer
    Jul 3, 2019 at 5:53

You can copy the text with the mouse if you do not have the mouse enabled (e.g. set mouse=), and enable number.

This will work in any terminal, and also seems to work in the GTK3 version of gvim (but may not work in all gvim versions).

From the perspective of the terminal there is no difference between the number column on the left and the buffer contents; it's all just text. This can be either a good or bad thing, depending on what you want. If you want to copy the number column then it's a good thing :-)

  • 1
    with mouse enabled, I think one can use shift + mouse click to copy. However, this might be problematic, if you have vertical split windows open. May 16, 2019 at 7:42

Why so complicated? The easy way to to this is with the grep and tee commands.

Disclaimer: before you start messing with files with the tee command make an alias in your .profile for the command:

alias tee="tee -a"

The -a flag tells tee to append to rather than obliterate the file. What tee does specifically is take stdout and redirects it to files, similar to

echo some text > file.

But it works with what is produced on the terminal.

In order to use tee properly we need to get some stdout and that is where grep comes in.

What you want to do is grep (find) the text you want to produce which by default will put the text as stdout. You can also add lines before or after the line you want with -A, -B, and -C flags. Also, to add line number you can add the -n flag. So if you add -A5 for example, you will get the line you grep for plus 5 lines after that. Similarly with -B5 but in this case you get the line you grep for plus 5 lines before what you grep for. -C5 you get 5 lines before and after meaning 10 lines plus what you grep for. The -n flag gets you your line numbers.

The command:

grep -n[-ABC][num] "search line" | tee [-a, unless you alias it already] [file]

This command is a lot more simple. You see everything on the screen. The only drawback (if it is a drawback) is that when grep adds line numbers, it does so with a colon and each line after that gets a dash like this:

33: text....
34- text....
35- text....

However seeing how you are injecting line numbers to begin with, this is a good visual clue, especially if you have line numbers enabled in your text editor.

It could get real confusing otherwise.


  • Welcome to Vi and Vim! Interesting answer to the question, but it doesn't really address how this integrates with vim.
    – D. Ben Knoble
    Oct 30, 2019 at 22:57
  • 1
    Actually integration is more of a Vim thing which isn't as consistent with the unix way of doing one thing and do it well. Straight up vi is and should be a text editor, thats all it should be resigned to. Grep and tee commands are better suited for those results. Why make life hard.
    – 14u2ponder
    Nov 2, 2019 at 19:24
  • 1
    Not here to argue about the philosophy—vim makes it easy to pull in these tools. My point is this a vi/vim site, so your answer should probably fit into that context.
    – D. Ben Knoble
    Nov 2, 2019 at 19:32

Your Answer

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

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