Search code examples
regexvimcounterreplace

How to search and replace with a counter-based expression in Vim?


Is there a way to insert the value from some sort of counter variable in Vim :substitute command?

For instance, to convert this document:

<SomeElement Id="F" ... />
<SomeElement Id="F" ... />
<SomeElement Id="F" ... />

to this resulting document:

<SomeElement Id="1" ... />
<SomeElement Id="2" ... />
<SomeElement Id="3" ... />

I imagine, the command would look like so:

:%s/^\(\s*<SomeElement Id="\)F\(".*\)$/\1<insert-counter-here>\2/g

I am using a very recent Windows build, from their provided installer. I strongly prefer not to install any additional tools. Ideally, I'd like to also avoid having to install scripts to support this, but I'm willing to, if it is the only way to do it.


Solution

  • Vim wiki instructions seems to be the easiest solution (at least for me).

    Example below replaces all occurences of PATTERN with REPLACE_[counter] (REPLACE_1, REPLACE_2 etc.):

    :let i=1 | g/PATTERN/s//\='REPLACE_'.i/ | let i=i+1
    

    To answer the question it might look like this:

    :let i=1 | g/SomeElement Id="F"/s//\='SomeElement Id="'.i.'"'/ | let i=i+1
    

    Alternative solution

    If anyone is interested in a solution with %s syntax I would advise to look at the @ib. answer which is:

    :let n=[0] | %s/Id="\zsF\ze"/\=map(n,'v:val+1')/g