Duplicate tip
This tip is very similar to the following:
These tips need to be merged – see the merge guidelines.
created April 5, 2001 · complexity basic · author Devin Weaver · version 5.7
The :set number displays line numbers. This tip, however, inserts the line numbers into the file.
On Unix, you can insert line numbers with a command like:
cat -n file > new_file
In Vim, you can use the global command to insert line numbers:
:g/^/exec "s/^/".strpart(line(".")." ", 0, 4)
This runs the exec command on every line that matches /^/ (matches every line).
The exec command takes a string and executes it as if it were typed in.
line(".")." " number of the current line plus four spaces
strpart("123 ", 0, 4) first four characters ("123 ")
"s/^/123 " substitute the beginning of the line with "123 "
See Insert line numbers with a Perl filter.
Comments
In Vim6, this is even easier. For more information, :help :s and look at the line about \=
:%s/^/\=strpart(line('.')." ",0,&ts)
In visual mode, type:
:s/^/\\=strpart((line('.')-line("'<")+1).' ',0,5)
Then you will get visual selection numbered as expected.
In Vim, call this function:
" Insert line numbers in front of lines.
function! Listing()
let i=line("$")
let pre = ' '
while (i > 0)
if match(i, '^9*$') == 0
let pre = pre . '0'
endif
call setline(i, pre . i . "\t" . getline(i))
let i=i-1
endwhile
endfunction
To number a selection (or even the whole document), piping through grep can be much faster and usually offers good results:
:'<,'>!grep -n -h ^
This numbers (-n) the lines it's piped through and strips the file-name headers (-h) that grep puts in. You can even select certain lines to number by changing the pattern to match (^ is the beginning of the line, but it could be a more complex pattern).
It's a bit faster than the other suggestions for a quick down-n-dirty numbering of lines. Small variations I've noted include:
- The other versions here have a fixed-width column--this could be a good thing or a bad thing.
- This one (at least with the version of grep I used) places a colon after the line numbers, which again could be good or bad.
- This does need grep to be available.
If you have the version with Python scripting, you can use the following:
:py << EOF from vim import * cb = current.buffer for i in range(len(cb)): cb[i] = str(i) + ' ' + cb[i] EOF
Also try this:
:%! nl -ba
If you have Perl support, just use these two commands:
:perl $linetoinsert=1;
:perldo if($_ =~ m/^[A-Z]/){ $_="$linetoinsert. $_"; $linetoinsert++;}
This will make sure it adds the line number only if the line starts with a capital letter. You can customize the regexp to handle white spaces too.
Since you had to type two commands to do this, I thought it would be better to add them into a single function that you could call. However, I couldn't get the line1,line2perldo ... statement to work inside a Vim function. I don't know why. But here is another alternative
" The -range option tells that our command takes a line range and puts them into <line1> and <line2>
:command! -range InsertLineNums call InsertLineNumbers(<line1>,<line2>)
function InsertLineNumbers(l1, l2)
let ln1 = a:l1
let ln2 = a:l2
let linetoinsert = 1
while ln1 <= ln2
let currLine = getline(ln1)
if currLine =~ '^[A-Z]'
let newLine = linetoinsert.". ".currLine
let linetoinsert = linetoinsert + 1
else
let newLine = " ".currLine
endif
call setline(ln1, newLine)
let ln1=ln1+1
endwhile
endfunction
If you want insert line numbers like "000103" , you can use:
:%s/^/\=substitute(printf("%4d",line("."))," ","0","g")