Vim Note | Making a list of 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.

你可能感兴趣的:(Vim Note | Making a list of numbers)