Tip 918 Printable Monobook Previous Next

created 2005 · complexity basic · version 6.0

This tip presents different methods showing how to insert a list of increasing numbers.

## Making a list

It is easy to insert a list of ascending numbers, for example, this command inserts five lines after the current line:

```:put =range(11,15)
```

The five lines are:

```11
12
13
14
15
```

If wanted, the lines can be inserted after a particular line number, for example `:123put =range(11,15)` inserts them after line number 123, while `:0put =range(11,15)` inserts the lines at the start of the buffer, and `:\$put =range(11,15)` inserts them after the last line.

An equivalent command is `:call append(123,range(11,15))`) to insert the five lines after line number 123, for example.

The list of numbers can be formatted. For example, the following inserts 150 lines, where each line contains a number displayed in four columns with leading zeros.

```:put =map(range(1,150), 'printf(''%04d'', v:val)')
```

The results range from `0001` to `0150`. The `map()` function replaces each value with the result of the expression, which must be given as a string (the double `''` presents a single apostrophe when inside an apostrophe-quoted string). In the expression, `v:val` represents each value from the list in the first argument.

Here is another example, using a loop rather than `map()`:

```:for i in range(1,10) | put ='192.168.0.'.i | endfor
```

Executing this command inserts the following after the current line:

```192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7
192.168.0.8
192.168.0.9
192.168.0.10
```

## Substitute with ascending numbers

Suppose you want to replace each occurrence of "`abc`" with "`xyz_N`" where N is an ascending number (`xyz_1`, `xyz_2`, `xyz_3`, and so on).

One approach uses the following command:

```:let i=1 | g/abc/s//\='xyz_'.i/ | let i=i+1
```

However, this only changes the first `abc` on each line. Adding the `g` flag for a global substitute does not help as `i` is only incremented once per matching line.

The following trick uses the `a` register which can be changed with the `setreg()` function:

```:let @a=1 | %s/abc/\='xyz_'.(@a+setreg('a',@a+1))/g
```

As setreg returns 0 rather than a useful value, the replacement expression (`\=`) calls `setreg` by adding it to register `a`.

## Using a function

Put the following script in your vimrc or in a file in your `plugin` directory.

```" Add argument (can be negative, default 1) to global variable i.
" Return value of i before the change.
function Inc(...)
let result = g:i
let g:i += a:0 > 0 ? a:1 : 1
return result
endfunction
```

Suppose you want to replace each occurrence of "`abc`" with "`xyz_N`" where N is an ascending number (`xyz_1`, `xyz_2`, `xyz_3`, and so on). To do this, enter the command:

```:let i = 1 | %s/abc/\='xyz_' . Inc()/g
```

For another example, the following command replaces each occurrence of "`abc`" with a number that increases by 5, starting at 100 (the numbers will be 100, 105, 110, and so on):

```:let i=100 | :%s/abc/\=Inc(5)/g
```

## Incrementing selected numbers

In Vim 8, the first number in a selection can be incremented by pressing Ctrl-A. If the selection covers several lines, the first number in the selection on each line is incremented. Alternatively, numbers in a selection covering several lines can be converted to a sequence by typing g Ctrl-A. For example, start with the following line:

```my_array[0] = 0;
```

Then copy it using `Y6p` (copy the line and paste it six times). The result is:

```my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
```

With the cursor on the first `0` in the first line, start a blockwise select by pressing Ctrl-V (or Ctrl-Q if you use Ctrl-V for pasting). Move the cursor down to select the first column of zeros, then press g Ctrl-A. Using Vim 8, that will give:

```my_array[1] = 0;
my_array[2] = 0;
my_array[3] = 0;
my_array[4] = 0;
my_array[5] = 0;
my_array[6] = 0;
my_array[7] = 0;
```

Vim 7 and earlier need a script or a macro to create a sequence.

An alternative is to make use of external `seq` command to generate the sequence and copy paste using visual block mode. E.g, see the below sample ex mode commands (you can copy paste these):

• `:new`
• This creates a new scratch window
• `:.!seq 1 15`
• This generate a sequence from 1 to 15,
• Use `seq -f \%2g 1 15` for right justification
• `:exe "normal! \<C-V>0G"`
• This selects the sequence in visual block mode and copies it
• This is same as typing the sequence `<CTRL-V>0Gy` in normal mode
• `:bw!`
• This nukes the new scratch window
• `:normal! p`
• Paste the copied sequence in the original buffer.
• This is same as typing `p` in normal mode
• Make sure you are back in the original window and also the right location before pasting.