I have lines like the following ones (actually function prototypes)

void ()
word ( word, another word, one_more word, ..., hello, ... )
one argument ( only )

I want to match each single argument and enclose it between < and >.

Before wasting time with the replacement string, I'm trying to devise the proper search pattern. The following command

:%s/\(( \|, \)\(.\{-}\)\( )\|,\)/\1<\2>\3/g

only matches and replace odd-position arguments.

1 Answer 1


It's because your matching groups have overlap! Exept for zero-width pattern items, every charachter in your string will be consumed in the matching. so here you can use \zs and \ze to confine your match:

:%s/\%(( \|, \)\zs\(.\{-}\)\ze\%( )\|,\)/<\1>/g

Here i also changed the first and third captuting groups to non-capturing as we don't need to capture them. for a complete list of zero-width pattern items, see: :h pattern-overview

  • Oh, this answer is what I was looking for! BTW, while waiting for it I tried another simpler search pattern %s/ \(\w[^,)]\+\)/<\1>/g. This is good too, but it fails when something (not necessarly a comment) follows the closing parenthesis. What do you think about it?
    – Enlico
    Commented Sep 18, 2016 at 22:12
  • @EnricoMariaDeAngelis So first capture anything between parethesis and do substitution on them; with your pattern: %s/(\zs\(.*\)\ze)/\=substitute(submatch(1), '\(\w[^,)]\+\)', '<\1>', 'g')
    – dNitro
    Commented Sep 18, 2016 at 23:52
  • Thank you for the answer. However I found another related question here.
    – Enlico
    Commented Sep 19, 2016 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.