How do I run a substitution only on lines that match a specific pattern using the global command?
Answer
:g/pattern1/s/pattern2/replacement/g
Explanation
Combining :g with :s lets you apply a substitution using two independent patterns: :g selects which lines to act on, and :s controls what gets replaced within those lines. This gives you precision that :s alone cannot provide, since :s matches both the filter and the replacement using the same regex.
How it works
:g/pattern1/— visits every line in the file that matchespattern1s/pattern2/replacement/g— on each of those lines, replaces all occurrences ofpattern2withreplacement
The two patterns are completely independent: pattern1 is the line filter, pattern2 is what you actually want to change.
Example
Suppose you have a JavaScript file and want to change var to let, but only in lines that declare functions:
var x = 1
function foo() { var y = 2 }
var helper = function() { var z = 3 }
Running :g/function/s/var/let/g produces:
var x = 1
function foo() { let y = 2 }
let helper = function() { let z = 3 }
The top-level var x = 1 is left untouched because that line does not match /function/.
Tips
- Use
:g!/pattern1/s/pattern2/replacement/gto invert the filter — substitute only on lines that do not matchpattern1 - Combine with
\v(very magic) for cleaner patterns::g/\vpattern1/s/\vpattern2/replacement/g - The
/gflag on:sis independent — omit it if you only want to replace the first occurrence per matching line - This technique composes with other
:gsubcommands::g/pattern/d,:g/pattern/m$, etc.