vimtricks.wiki Concise Vim tricks, one at a time.

How do I replace each match with an incrementing number using a counter variable in Vim?

Answer

:let i=0 | g/pattern/s/pattern/\=printf('%d', i+=1)/

Explanation

By combining :let, the :g global command, and an expression substitution with \=, you can replace every match of a pattern with a unique incrementing number. This is useful for numbering items, tagging duplicates, or generating sequential identifiers without plugins.

How it works

  • :let i=0 — initialises a counter variable to zero
  • | — chains the next command on the same command line
  • :g/pattern/ — iterates over every line matching pattern
  • s/pattern/\=.../ — substitutes the match using a Vimscript expression
  • printf('%d', i+=1) — increments i and formats it as a decimal number

The \= in the replacement string tells Vim to evaluate the following expression, so each invocation gets a fresh value of i.

Example

Given this buffer:

FIX: crash on startup
FIX: memory leak in parser
FIX: incorrect return value

Running :let i=0 | g/FIX/s/FIX/\=printf('FIX-%02d', i+=1)/ produces:

FIX-01: crash on startup
FIX-02: memory leak in parser
FIX-03: incorrect return value

Tips

  • Change '%d' to '%02d' for zero-padded numbers like 01, 02, 03
  • Use submatch(0) to reference the original matched text inside the expression: \=printf('[%d] %s', i+=1, submatch(0))
  • The counter persists in Vimscript scope for the session, so re-run :let i=0 if you need to reset it
  • For non-sequential replacements, swap i+=1 with any Vimscript expression that returns a string

Next

How do I prepend a value to the front of a comma-separated Vim option like path or runtimepath?