Vim's regex dialect differs from PCRE; knowing its tools turns hard refactors into one substitute.
Vim's default magic mode treats . * [] ^ $ as special but needs backslashes for \+, \?, \|, \(\) and \{n,m}. Starting a pattern with \v (very magic) makes every punctuation character special, closer to PCRE: /\v(foo|bar)+ instead of /\(foo\|bar\)\+. \V (very nomagic) does the opposite, so only \ is special, useful for literal text.
Vim-specific atoms:
\<\>word boundaries (in\vmode just<>).\zsand\zeset where the match starts and ends while still requiring the context:/foo\zsbarmatchesbaronly afterfoo. This replaces most lookbehind/lookahead needs.- Real lookarounds exist too:
\(foo\)\@<=bar,foo\(bar\)\@!. \{-}is the non-greedy quantifier (.\{-}vs.*); in very magic{-}.\_sand\nmatch across line breaks;\_.is any character including newline.\c/\Canywhere in the pattern force case-insensitive / sensitive.
In a replacement, \= evaluates an expression, with submatch(n) for groups: :%s/\d\+/\=submatch(0)*2/g doubles every number. \u/\U/\L change case of what follows. These combine with :g for surgical refactors.
Example
/\v(get|set)_\w+ " very magic: no backslash soup
/\Vfile.txt " literal text: '.' is just a dot
:%s/\vuser_\zsid/ident/g " rename only the 'id' part of user_id
:%s/".\{-}"/"X"/g " non-greedy: "hi" and "yo" -> "X" and "X"
:%s/\d\+/\=submatch(0) * 2/g " double every number
:%s/\v<(\w)(\w*)>/\u\1\L\2/g " Title Case every word
:%s/,\n\s*/, / " join continuation linesRemember
- \v very magic = PCRE-like, \V = literal
- \zs/\ze trim the match but keep the context
- \{-} is non-greedy; \= computes the replacement
Watch out for
- Pasting a PCRE pattern like (a|b)+ into a default-magic search; without \v it looks for literal parentheses.