How do I write a Vim search pattern that matches text spanning multiple lines?
Answer
/pattern1\_.{-}pattern2
Explanation
Vim's regex engine normally treats . as matching any character except a newline, making cross-line matches impossible. The \_ prefix turns any character class or . into a newline-aware version, enabling true multi-line search patterns.
How it works
\_.— matches any single character including newlines (unlike.which stops at end-of-line)\_.{-}— non-greedy match of any characters including newlines ({-}is Vim's non-greedy quantifier)\_s— matches any whitespace including newlines (\sonly matches inline whitespace)\_[abc]— matchesa,b,c, or a newline
Example
Given a buffer:
function foo(
arg1,
arg2
)
To find foo(...) even when the argument list spans multiple lines, use the non-greedy form:
/foo(\_.{-})
The greedy \_.* would match from the first ( all the way to the last ) in the file. Always prefer {-} with multi-line patterns to avoid over-matching.
Tips
- Combine with
\zs/\zeto narrow the highlighted region:/foo(\zs\_.{-}\ze)highlights only the argument content \_s\+is a useful pattern for collapsing runs of whitespace that may include blank lines- Use
:set hlsearchandn/Nto visually confirm multi-line match boundaries - In substitute commands,
\nin the replacement inserts a literal newline, while\_.in the pattern matches across newlines