How do I run a global command only on lines that match two different patterns simultaneously?
Answer
:g/pattern1/g/pattern2/command
Explanation
Vim's :g command can be nested — the command part of one :g can itself be another :g. This lets you filter lines by multiple patterns without needing complex regex AND operators.
How it works
- The outer
:g/pattern1/iterates over every line matchingpattern1 - For each matching line, the inner
g/pattern2/commandis executed, which further filters bypattern2 - The final command only runs on lines that match both patterns
This is equivalent to logical AND: pattern1 AND pattern2.
Example
Delete all lines that contain both "TODO" and "FIXME":
:g/TODO/g/FIXME/d
Given a buffer:
# TODO: update this
# FIXME: broken logic
# TODO: FIXME this first!
# Note: see above
Only the line with both TODO and FIXME is deleted, leaving:
# TODO: update this
# FIXME: broken logic
# Note: see above
Tips
- Any Ex command can go at the end:
pto print matching lines,s/old/new/to substitute, etc. - To delete lines matching pattern1 but not pattern2, use
:g/pattern1/v/pattern2/d(inner:vinverts) - An alternative for simple two-pattern AND in substitution:
:g/pattern1/s/pattern2/replacement/ - The same approach works with
:vnesting::v/required/g/warning/ddeletes lines missingrequiredthat also containwarning