How do I run a macro only on lines that match a specific pattern?
Answer
:g/pattern/normal @a
Explanation
The :g (global) command combined with :normal @a lets you execute a recorded macro only on lines matching a pattern. This is surgical automation — instead of running a macro on every line or manually jumping between matches, you let Vim find the targets and apply the macro in one shot.
How it works
:g/pattern/selects every line in the file that matchespatternnormal @aruns the macro stored in registeraas a normal mode command- Vim processes each matching line one at a time, positioning the cursor at the beginning of the line before executing the macro
- Lines that do not match the pattern are completely untouched
Example
Suppose you have a CSS file and you want to double every pixel value, but only on lines containing margin:
margin: 10px;
padding: 20px;
margin: 5px;
border: 1px solid;
margin-top: 15px;
First, record a macro that doubles the number on the current line:
qa0/\d\+<CR>ciw<C-r>=submatch(0)*2<CR><Esc>q
Or more simply, if there is one number per line:
qa0f:w<C-a>q
Then apply it only to margin lines:
:g/margin/normal @a
The padding and border lines remain unchanged.
Tips
- Use
:g!/pattern/normal @aor:v/pattern/normal @ato run the macro on lines that do not match - The macro runs with the cursor at column 1 of each matching line, so design your macro to work from the beginning of a line
- Use
norm!instead ofnormalto ignore custom mappings and use default Vim behavior — this is safer and more predictable - You can chain this with ranges:
:10,50g/pattern/normal @alimits execution to lines 10 through 50 - If the macro modifies line numbers (e.g., deletes or adds lines),
:gmay behave unexpectedly because it pre-scans line addresses — test on a small range first - Combine with
:wafterward to save::g/pattern/normal @a | w - This technique effectively replaces many complex
:scommands — sometimes a macro is easier to record than a regex is to write