Batch Number Increment in Vim
Desktop Source Code is licensed under Creative Commons Zero
We’re fans of Vim at Collective Idea, with the largest percentage of our staff using it as their primary editor. We’ve even added a few recent [1] converts. Go Vim!
Setting the Stage
This morning I needed to quickly increment multiple sets of numbers. Too tedious to edit each number by hand, I wanted to figure out how to best do this with Vim.
We’ll use a simplified example to demonstrate the task at hand — globally increment a series of numbers by a given value. The first block of HTML is the original code and the second block of HTML is the desired output:
Here are the steps I took and what I found.
A First Pass
I initially reached for Vim’s CTRL-A, a very handy tool for incrementing[2] numbers. Anywhere on the line, 3
Awesome! Except that that only increments the first number and Vim’s single-repeat repeater, instead of moving to the next number, re-increments that number again by 3.
Perhaps one of Vim’s other repeaters, a macro, or single-repeat with an added motion would have worked, but as with most tasks in Vim with excessive repeated keystrokes there’s usually a better way.
Enter Sub-Replace-Expression
Vim’s sub-replace-expression allows the second half of a substitution to contain logic to be evaluated. Prepending a \= signals to Vim that what’s to follow should first be evaluated before being used as the replacement value in the substitution.
In our example, visual line select the second set of
:'<,'>s/\\d\\+/\\=submatch(0)+3/g
. Presto!
# match against 1 or more digits
\d\+
# begin replace expression
\=
# submatch({nr})
#
# return the nth submatch of the matched text, 0 returns
# the whole matched text; add 3
submatch(0)+3
# perform the substitution globally
/g
[1] A convert in progress. I believe in you, Jonathan.
[2] CTRL-X handles decrementing.
Comments