Reputation: 121
I wrote a section of a webpage that had the following bit...
<span id="item01"> some first presented text</span>
<span id="item02"> some other text, presented second</span>
<span id="item03"> more text</span>
....
<span id="item15"> last bit of text.</span>
I then realized that it should have been numbered from 14 to 0, not 1 to 15. (Yes, bad design on my part, not planning out the JavaScript first.)
Question. Is there an easy way in vim to do math on the numbers in a regular expression? What I would like to do is a search on the text "item[00-99]", and have it return the text "item(15-original number)"
The search seems easy enough -- /item([0-9][0-9])/
(parentheses to put the found numbers into a buffer), but is it even possible to do math on this?
Macro for making numbered lists in vim? gives a way to number something from scratch, but I'm looking for a renumbering method.
Upvotes: 8
Views: 1394
Reputation: 8715
Another interesting way is to use g<CTRL-a>
(:help v_g_CTRL-A
for more information)
Start from
<span id="item01"> some first presented text</span>
<span id="item02"> some other text, presented second</span>
<span id="item03"> more text</span>
....
<span id="item15"> last bit of text.</span>
Use visual block mode to reset all numbers to 00
:
<CTRL-V>
select all numbersr0
replace all numbers with zerosYou should be seen:
<span id="item00"> some first presented text</span>
<span id="item00"> some other text, presented second</span>
<span id="item00"> more text</span>
....
<span id="item00"> last bit of text.</span>
Now restore your block select with gv
or just select all lines with V
and press g<CTRL+a>
<span id="item01"> some first presented text</span>
<span id="item02"> some other text, presented second</span>
<span id="item03"> more text</span>
....
<span id="item015"> last bit of text.</span>
Unfortunately one last clean up is needed here. As you can see, all two digit numbers get 0
in front. Use visual block mode <CTRL+v>
again to select and remove unwanted zeros.
<span id="item01"> some first presented text</span>
<span id="item02"> some other text, presented second</span>
<span id="item03"> more text</span>
....
<span id="item15"> last bit of text.</span>
Now you are done :)
Upvotes: 7
Reputation: 3086
You might want to take a look at the VisIncr plugin. It adds support for increasing / decreasing columns of numbers, dates, and day names, in various formats. Quite handy when you have to deal with these kind of things.
Upvotes: 2
Reputation: 5347
If you have vim with perl (many distributions have that by default), you can
use :perldo
commands to do it. (@Marth solution is better)
:perldo s/(?<=item)(\d+)/15 - $1/e
Upvotes: 2
Reputation: 24812
:%s/item\zs\d\+/\=15 - submatch(0)/
will do what you want.
Breaking it down:
item\zs\d\+
: match numbers after item
(the \zs
indicates the beginning of the match)\=
: indicate that the replace is an expression15 - submatch(0)
: returns 15 minus the number matchedUpvotes: 12