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

How do I replace text using a custom Vimscript function in a substitution?

Answer

:%s/pattern/\=MyFunc(submatch(0))/g

Explanation

The \= prefix in Vim's substitute replacement invokes the expression register, which can call any Vimscript function. By defining a custom function, you can perform arbitrarily complex transformations during search-and-replace.

Define a function

function! CamelToSnake(word)
  return substitute(a:word, '[A-Z]', '_\l\0', 'g')
endfunction

Use it in a substitution

" Convert camelCase to snake_case across the file
:%s/\<[a-z]\w*[A-Z]\w*\>/\=CamelToSnake(submatch(0))/g

Built-in functions you can use

" Convert to uppercase
:%s/\<\w\+\>/\=toupper(submatch(0))/g

" Convert to lowercase
:%s/\<\w\+\>/\=tolower(submatch(0))/g

" Get string length
:%s/\w\+/\=strlen(submatch(0))/g

" Use printf for formatting
:%s/\d\+/\=printf('%04d', submatch(0))/g

" Use a counter (increment for each match)
:let c=0 | :%s/ITEM/\='item_' . (c+1)/g

Practical example: URL encode spaces

:%s/ /\=printf('%%%02X', char2nr(submatch(0)))/g

This replaces every space with %20.

Tips

  • submatch(0) is the full match, submatch(1) is the first capture group, etc.
  • You can call any Vim function, even user-defined ones
  • The function must return a string
  • For complex multi-step replacements, define a function first — it's cleaner than an inline expression
  • Documented under :help sub-replace-expression

Next

How do I run the same command across all windows, buffers, or tabs?