How do I search for a pattern that spans multiple lines?
Answer
/foo\_.*bar
Explanation
Vim's default . in regex matches any character except a newline, so a pattern like /foo.*bar only finds matches on a single line. By using \_.* instead of .*, you tell Vim that the dot should also match newline characters, allowing your search to span across line boundaries.
How it works
\_is a modifier that makes the next character class also match\n(newline)\_.means "any character including newline" (compared to.which excludes newlines)\_.*matches any number of characters across any number of lines- So
/foo\_.*barfindsfoofollowed bybaranywhere later in the file, even across multiple lines
Example
Given the text:
function foo() {
let x = 1;
return bar(x);
}
Searching with /foo.*bar finds nothing because foo and bar are on different lines.
Searching with /foo\_.*bar matches from foo on line 1 all the way to bar on line 3, highlighting the entire multi-line span.
Common multi-line patterns
" Find an opening HTML tag followed by its closing tag (across lines)
/<div\_.*<\/div>
" Find a function signature followed by a return statement
/function\_.*return
" Match an if-block opening to its closing brace
/if (\_.*}
Tips
- Use
\_.\{-}for a non-greedy multi-line match (equivalent to.*?in Perl regex):/foo\_.\{-}barmatches the shortest span fromfooto the nearestbar - Without
\{-},\_.*is greedy — it matches from the firstfooto the lastbarin the entire file - The
\_modifier works with character classes too:\_smatches any whitespace including newlines,\_[a-z]matches lowercase letters or newlines - Combine with substitution for multi-line replacements:
:%s/foo\_.*bar/replacement/g— but be careful with greedy matching - In very magic mode (
\v), you still need\_for newline-spanning:/\vfoo\_.{-}bar - Multi-line search can be slow on very large files because Vim must scan across line boundaries — use
\_.\{-}(non-greedy) whenever possible to limit the scan - Use
\nin the search pattern to match a literal newline character at a specific point:/foo\nbarmatchesfooat the end of one line immediately followed bybarat the start of the next