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

How do I fix or modify a recorded macro without re-recording it from scratch?

Answer

:let @a = substitute(@a, 'old', 'new', 'g')

Explanation

Macros are plain text stored in registers, which means you can patch them using Vimscript's substitute() function — no re-recording needed. This is invaluable when you have a long macro with a small mistake deep in the middle.

How it works

substitute({expr}, {pat}, {sub}, {flags}) works like a string-level s/// — it takes the current contents of register a (via @a), replaces matches of {pat} with {sub}, and assigns the result back:

:let @a = substitute(@a, 'oldcmd', 'newcmd', 'g')

Other useful transformations:

  • Prepend a step: :let @a = 'dd' . @a
  • Append a step: :let @a = @a . 'j'
  • Remove the last keystroke: :let @a = @a[:-2] (Vim uses 1-based index; [:-2] drops the final character)
  • Inspect before editing: :echo @a — shows the raw keystroke sequence with special characters visible

Example

You recorded a macro that appends a semicolon and moves down, but forgot the 0 to go to line start first:

:echo @a
" output: A;^[j
:let @a = '0' . @a
:echo @a
" output: 0A;^[j

Now run the corrected macro: @a

Tips

  • Special keys in macros appear as literal control characters (e.g., <Esc> shows as ^[). The substitute() call works on these raw bytes, so match them literally if needed
  • :reg a shows the register content in a human-readable format useful for inspection before editing
  • Pair with :let @a = @a[:-2] when the last recorded keystroke was accidental (a common issue when q or <Esc> slips in at the end)

Next

How do I use capture groups in Vim substitutions to rearrange or swap matched text?