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

How do I zero-pad numbers with :substitute using an expression replacement?

Answer

:%s/\v(\d+)/\=printf('%04d', submatch(1))/g<CR>

Explanation

When you need to normalize IDs, ticket numbers, or sequence values, :substitute can do more than plain text replacement. With an expression replacement (\=), Vim evaluates code for each match, so you can transform numbers on the fly instead of running external scripts. This is especially useful in migration files, logs, or config snippets where number width must be consistent.

How it works

  • :%s/.../.../g runs substitution across the whole buffer and replaces all matches per line
  • \v enables very-magic mode so the regex is less escaped
  • (\d+) captures one or more digits as group 1
  • \=... tells Vim to evaluate the replacement as an expression
  • printf('%04d', submatch(1)) formats the captured number as 4 digits with leading zeros

Because the replacement is computed per match, each number is formatted independently. You can swap %04d to %06d (or any width) without changing the matching logic.

Example

Before:

ID 7
ID 42
ID 105

Run:

:%s/\v(\d+)/\=printf('%04d', submatch(1))/g

After:

ID 0007
ID 0042
ID 0105

Tips

  • Use \=printf('%08X', submatch(1)) for uppercase hex formatting
  • Combine with a narrower pattern (for example ID\s+\zs\d+) when you only want specific numbers

Next

How do I append new keystrokes to an existing macro register without re-recording it?