vim -- How to read range of lines from a file into current buffer

Vim

Vim Problem Overview


I want to read line n1->n2 from file foo.c into the current buffer.

I tried: 147,227r /path/to/foo/foo.c

But I get: "E16: Invalid range", though I am certain that foo.c contains more than 1000 lines.

Vim Solutions


Solution 1 - Vim

:r! sed -n 147,227p /path/to/foo/foo.c

Solution 2 - Vim

You can do it in pure Vimscript, without having to use an external tool like sed:

:put =readfile('/path/to/foo/foo.c')[146:226]

Note that we must decrement one from the line numbers because arrays start from 0 while line numbers start from 1.

Disadvantages: This solution is 7 characters longer than the accepted answer. It will temporarily read the entire file into memory, which could be a concern if that file is huge.

Solution 3 - Vim

The {range} refers to the destination in the current file, not the range of lines in the source file.

After some experimentation, it seems

:147,227r /path/to/foo/foo.c

means insert the contents of /path/to/foo/foo.c after line 227 in this file. i.e.: it ignores the 147.

Solution 4 - Vim

Other solutions posted are great for specific line numbers. It's often the case that you want to read from top or bottom of another file. In that case, reading the output of head or tail is very fast. For example -

:r !head -20 xyz.xml

Will read first 20 lines from xyz.xml into current buffer where the cursor is

:r !tail -10 xyz.xml 

Will read last 10 lines from xyz.xml into current buffer where the cursor is

The head and tail commands are extremely fast, therefore even combining them can be much faster than other approaches for very large files.

:r !head -700030 xyz.xml| tail -30

Will read line numbers from 700000 to 700030 from file xyz.xml into current buffer

This operation should complete instantly even for fairly large files.

Solution 5 - Vim

I just had to do this in a code project of mine and did it this way:

In buffer with /path/to/foo/foo.c open:

:147,227w export.txt

In buffer I'm working with:

:r export.txt

Much easier in my book... It requires having both files open, but if I'm importing a set of lines, I usually have them both open anyway. This method is more general and easier to remember for me, especially if I'm trying to export/import a trickier set of lines using g/<search_criteria/:.w >> export.txt or some other more complicated way of selecting lines.

Solution 6 - Vim

You will need to:

:r /path/to/foo/foo.c
:d 228,$
:d 1,146

Three steps, but it will get it done...

Solution 7 - Vim

> A range permits a command to be applied to a group of lines in the current buffer.

So, the range of read instruction means where to insert the content in the current file, but not the range of file that you want to read.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAman JainView Question on Stackoverflow
Solution 1 - VimboxxarView Answer on Stackoverflow
Solution 2 - VimjoeytwiddleView Answer on Stackoverflow
Solution 3 - VimStewart JohnsonView Answer on Stackoverflow
Solution 4 - VimrajView Answer on Stackoverflow
Solution 5 - VimDigitalAce69View Answer on Stackoverflow
Solution 6 - VimPaulBView Answer on Stackoverflow
Solution 7 - VimJustinView Answer on Stackoverflow