Vim Tips Wiki
Advertisement
Tip 971 Printable Monobook Previous Next

created August 13, 2005 · complexity advanced · author Ciaran McCreesh · version 6.0


Say you have a document:

foo bar
bar foo
bar
foo

and you want to replace the first foo with blah_1, the second with blah_2, the third with blah_3 and so on. There are a number of options. The most obvious is:

:let i=1 | g//s/foo/\="blah_".i/ | let i = i + 1

This only works if foo only occurs at most once per line. Changing to a global substitute doesn't help, as i will only be incremented once per matching line. The solution is to use setreg():

:let @a=1 | %s/foo/\="blah_".@a.(setreg('a',@a+1)?'':'')/g

Unfortunately, setreg returns 0 rather than the value of the register it set, so we need to use a ?: block to eliminate this. Another option, which is only available in vim7:

:let i=[] | %s/foo/\="blah_".len(add(i,''))/g

This uses a growing list rather than a number.

Comments

The canonical way to solve this is by way of a function. Define something like

fun CountUp()
  let ret = g:i
  let g:i = g:i + 1
  return ret
endf

Then you can simply say

:let i = 1 | %s/foo/\="bar_" . CountUp()/g

Advertisement