Macros

There are moments when you look at a file and realize you need to make the same change on fifty lines — but each line is slightly different, so a simple search-and-replace won't work. This is where macros shine.

A macro is a recorded sequence of keystrokes stored in a register (see Registers for a deep dive into how registers work). You perform the edit once while Vim watches, and then you can replay it as many times as you need. Think of it as teaching Vim by example: "Watch what I do to this line, then do the same thing to the rest."

Macros bridge the gap between manual editing (too slow for repetitive work) and scripting (too complex for one-off tasks). They are one of Vim's most practical features for everyday editing.

What you'll learn in this chapter:

  • Record, replay, and edit macros stored in registers

  • Use recursive macros to process an unknown number of lines automatically

  • Set macros via the command line with escape sequences for special keys

  • Run macros across line ranges, visual selections, and pattern-matched lines with :g

  • Apply practical macro techniques for tasks like CSV-to-SQL conversion and arithmetic

Recording a Macro

  1. Press q{register} to start recording (e.g., qa)

  2. Perform your edits

  3. Press q to stop recording

  4. Press @{register} to replay (e.g., @a)

  5. Press @@ to repeat the last macro

Tip: Before recording, clear the register with qaq to avoid leftover content.

Example: Calculating Math Expressions

Given lines like:

Record a macro to compute and append the result:

Breakdown:

  • 0 — go to column 0

  • y$ — copy to end of line

  • A = — append = at end

  • <C-r>= — open expression register

  • <C-r>0 — paste register 0 (the copied expression)

  • <Enter> — evaluate the expression

  • <Esc> — back to Normal mode

  • j — move down one line

Now run it: 3@a to apply on 3 lines.

Example: Incrementing Numbers

Given: At the line 1 I have 150

Record a macro to copy the line, increment the first number by 1, and add 150 to the second:

Run it 10 times: 10@a

Editing a Macro

Since macros are just register content, you can edit them:

  1. Paste the macro content: "ap (in a new line)

  2. You'll see something like: yyp^Awww150^A

  3. Edit the text as needed

  4. Select the edited content and yank back: "ayiW

Note: When pasting a macro for editing, use Ctrl+rCtrl+r (double) to insert literally, preserving control characters.

Note: Vim differentiates WORD from word. A WORD is delimited by whitespace. A word is delimited by non-keyword characters. See :help WORD and :help iskeyword.

Setting Macros via Command Line

Setting macros with :let @{reg}= and double quotes lets you use escape sequences for special keys:

Escape sequence
Key

\<CR> or \<Enter>

Enter

\<Esc>

Escape

\<C-r>

Ctrl+r

\<C-a>

Ctrl+a

\<C-x>

Ctrl+x

Running Macros on Multiple Lines

Recursive Macros

A recursive macro calls itself at the end, running until it encounters an error (like reaching the end of the file). This is powerful for processing an unknown number of lines.

Run it with @a — it will keep going until f" fails (no more quotes on a line) or j fails (no more lines).

Tip: Always clear the register with qaq before recording a recursive macro. If the register has leftover content, the recursion will behave unexpectedly.

Appending to a Macro

Since macros are registers, you can append to them using the uppercase register:

Practical Example: CSV to SQL

Given CSV data:

Record a macro to convert each line to an SQL INSERT:

Result after 2@a:

Tips for Robust Macros

  1. Start at a known position: Begin with 0 or ^ to go to the start of the line

  2. End at the next line: Finish with j so the macro is ready for the next iteration

  3. Use word motions: Prefer w, b, e over l for more flexible macros

  4. Use search: /pattern<CR> to find the target instead of counting characters

  5. Test on one line first: Always test before running on many lines

  6. Clear first: Always qaq before recording into register a

  7. Combine with global: Use :g/pattern/ normal @a for selective application (see The Global Command)

  8. Use :normal: When :g + normal @a isn't enough, use :5,20 normal @a for ranges

Summary

Macros are Vim's answer to repetitive editing tasks that fall between simple substitution and full scripting. By recording a sequence of keystrokes into a register, you can replay complex edits across any number of lines. Recursive macros automate processing of unknown quantities of data, while the ability to edit macro contents and combine macros with the global command gives you precise control over batch text transformations.

Key takeaways:

  • Always clear the target register (qaq) before recording a macro to prevent leftover content from interfering.

  • Design robust macros by starting at a known position (0 or ^) and ending on the next line (j).

  • Use :let @a="..." with escape sequences to set macros programmatically via the command line.

  • Combine macros with :g/pattern/normal @a or :5,20 normal @a to apply them selectively across lines.

Exercises

  1. Record and replay a basic macro — Given a list of names (one per line), record a macro that wraps each name in double quotes and adds a comma at the end (e.g., Alice becomes "Alice",). Apply it to all lines.

  2. Edit an existing macro — Record a macro into register b that uppercases the first word of each line. Then edit the macro to also add a period at the end of the line. Replay the modified macro.

  3. Recursive macro for quote replacement — Given a file where some lines use double quotes and you want to replace all double quotes with single quotes, record a recursive macro that processes every line until the end of the file.

  4. Macro with arithmetic — Given lines containing item_01, item_01, item_01 (all the same number), record a macro that increments the number on each successive line so they become item_01, item_02, item_03, and so on.

  5. Combine macro with the global command — Given a file with mixed content, run a macro only on lines that start with > (quoted lines). The macro should remove the > prefix and capitalize the first letter of the line.

Last updated

Was this helpful?