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

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 matching pattern1
  • For each matching line, the inner g/pattern2/command is executed, which further filters by pattern2
  • 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: p to print matching lines, s/old/new/ to substitute, etc.
  • To delete lines matching pattern1 but not pattern2, use :g/pattern1/v/pattern2/d (inner :v inverts)
  • An alternative for simple two-pattern AND in substitution: :g/pattern1/s/pattern2/replacement/
  • The same approach works with :v nesting: :v/required/g/warning/d deletes lines missing required that also contain warning

Next

What is the difference between the inner word (iw) and inner WORD (iW) text objects in Vim?