How do I extract regex capture groups from a string in Vimscript?
Answer
matchlist()
Explanation
matchlist({str}, {pattern}) runs a regex match and returns a list of all captured groups, making it the idiomatic way to extract structured data from strings in Vimscript. Index 0 holds the full match; indices 1–9 hold the contents of each \(…\) group.
How it works
let parts = matchlist('2024-03-15', '\(\d\{4}\)-\(\d\{2}\)-\(\d\{2}\)')
" parts[0] = '2024-03-15' (full match)
" parts[1] = '2024' (year)
" parts[2] = '03' (month)
" parts[3] = '15' (day)
Returns an empty list [] if the pattern does not match — so always guard:
let m = matchlist(line, pattern)
if !empty(m)
let year = m[1]
endif
Example
Parse function signatures from Go-style code:
function! ParseFunc(line)
let m = matchlist(a:line, 'func \(\w\+\)(\(.*\))')
if empty(m)
return
endif
echom 'Name: ' . m[1] . ', Args: ' . m[2]
endfunction
call ParseFunc('func Connect(host string, port int)')
" Output: Name: Connect, Args: host string, port int
Tips
- Related:
matchstr({str}, {pat})returns only the full match string;match({str}, {pat})returns the byte offset. - Use
\v(very magic) to write patterns with less escaping:matchlist(s, '\v(\d{4})-(\d{2})-(\d{2})') - In Neovim Lua:
vim.fn.matchlist(str, pattern)works identically. - For simple existence checks, prefer
match(str, pat) != -1over!empty(matchlist(...)).