sponsor Vim development Vim logo Vim Book Ad

basic Tip #65: Insert line number into the actuall text of the file.

 tip karma   Rating 348/116, Viewed by 7848 

Read and edit this tip on the Vim tip wiki. The wiki may have a more recent version of this tip.

created:   April 5, 2001 16:59      complexity:   basic
author:   Devin Weaver      as of Vim:   5.7

Although :set number will add nice line number for you At time you may wish to actually place the line numbers into the file. For example on GNU Unix you can acomplish a simular task using cat -n file > new_file

In VIM you can use the global command to do this

:g/^/exec "s/^/".strpart(line(".")."    ", 0, 4)

What this does is run the exec comand on every line that matches /^/ (All)
The exec command taks a string and executes it as if it were typed in.

line(".")."    " -> returns the number of the current line plus four spaces.
strpart("123    ", 0, 4) -> returns only the first four characters ("123 ").
"s/^/123 " -> substituts the begining of the line with "123 ".

 rate this tip  Life Changing Helpful Unfulfilling 

<< Always set your working directory to the file you're editing | Transfer text between two Vim 'sessions', >>

Additional Notes

[email protected], April 5, 2001 17:02
Hmmm. Silly me I forgot HTML contracts spaces. Perhaps a pre comand would be usefull.

<pre>
:g/^/exec "s/^/".strpart(line(".")."    ",0,4)
</pre>
[email protected], June 4, 2001 23:13
In Vim6, this is even easier.  For more information,  :help :s and look at the line about \=

:%s/^/\=strpart(line('.')."        ",0,&ts;)
[email protected], July 25, 2001 16:38

How about in visual mode, type

:s/^/\\=strpart((line('.')-line("'<")+1).'     ',0,5)

Then you will get visual selection numbered as  expected
[email protected], August 29, 2002 13:01
I've found that to number a selection (or even the whole document) piping it through grep (available now for your favorite platform, operators are standing by to take your orders) can be much faster and usually offers the results I want.

:'<,'>!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 just the beginning of the line, but it could be a more complex formula)

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 around...not a problem for most folks, but it might be an issue

-tim
[email protected], January 5, 2003 6:46

You might as well add numbers in the file by simply typing
:%!cat -n

-docelic
Anonymous, December 15, 2003 12:00
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
Goutham, April 21, 2004 23:44
Also try this,

:%! nl -ba
dsdsdsd, September 20, 2004 4:15
sdsdsd
[email protected], August 4, 2006 14:34
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 caiptal letter. You can customize the regexp to handle white spaces too.                                                                                                                      
[email protected], August 25, 2006 12:53
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 coudlnt get the line1,line2perldo ... statement to work inside a vim function. I dunno 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

enjoy!!
Anonymous, December 22, 2006 1:29
If you want insert line number like "000103" , you can use this below.
:%s/^/\=substitute(printf("%4d",line("."))," ","0","g")
If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to the maillist. Help Bram help Uganda.
   
Sponsored by Web Concept Group Inc. SourceForge.net Logo