I know in vim I can use :global to execute commands on the matching lines.

But I'm wondering if it's possible to execute those commands on every matching pattern, not just lines, consider following example:

aaa bbb
aaa ccc aaa ddd ww

I want to perform action: normal wdw on every matching aaa, so I expect the result to be:

aaa aaa ww

But with global, it will only do the action once on the 2nd line.


This is job for :substitute


after the pattern (\zs), I match spaces (\s\+) followed by any number of non spaces (\S\+).

If you really want dw and not dW, you'll prefer \(\k\@!.\)\+\k\+ instead of \s\+\S\+

  • 1
    My first inclination was to suggest substitute, too, but the problem is you need to figure out a new pattern any time you change the command. With macro approach you can just drop in different normal mode commands (as long as they operate between patterns). For simply solving wdw, though, this is the most straightforward way. – B Layer Sep 3 '17 at 12:42
  • Typo? \S\+\s\+ at end of last sentence doesn't match what you have in the substitute command: \s\+\S\+. – B Layer Sep 3 '17 at 12:57
  • @BLayer, if the command was more complex, I may not have used :s. here, it's about deleting something. The movement also is not that complex. it's a movement full of side effects. For instance, in aaa, bbb, w will stop at the first coma. That's why I usually prefer regexes. BTW, thanks for noticing the typo. – Luc Hermitte Sep 3 '17 at 13:55
  • Sure. I was going more by the subject, "execute command on every matching pattern", rather than the particular example but neither way of looking at it is more valid than the other. – B Layer Sep 3 '17 at 15:14

You might be interested by this question: Run a command on every match of a search (not on the line). The answer suggests the use of sub-replace-expression but this is more adapted when the changes are localized to the matches, and requires you to define a function.

However if the command changes often you would be better off using macros.

Here is one way to do it on your snippet, with the explanation:

  • gg Go to the top
  • /aaa<CR> Search to go on the first match
  • qq Start recording a macro into the q register
  • wdw Execute your commands, be careful where your cursor lands
  • Nn Needed to put the cursor on the next match every time in this case
  • q Stop recording
  • 2@q Play two times, or use a recursive macro but mind your &wrapscan as B Layer explained
  • Now we don't necessarily have to write functions: we can use lambdas as well: see for instance: %s/aaa/\={ s -> toupper(s)}(submatch(0))/g – Luc Hermitte Sep 3 '17 at 12:09
  • Nice indeed! But I can't figure out how to alter the text around the match, e.g. deleting the next word (wdw). Is this possible with the original search pattern? – LEI Sep 3 '17 at 12:15
  • Sorry. After giving more thoughts into it, lambda are pointless here as they return an expression. They are not full-fledged functions. toupper(submatch(0)) is more than enough in my example. My mistake. – Luc Hermitte Sep 3 '17 at 13:58

There's nothing like it mentioned anywhere in repeat.txt (:h repeating) so one can probably conclude that there's no native support for it.

If you're running this on the whole file a recursive macro is a viable approach. These commands demonstrate the macro which is nwdwN@q ...

:let @/ = "aaa"
:let @q = "nwdwN@q"
:set nowrapscan
:set wrapscan

(This assumes your searches wrap around the end of files. Otherwise you can leave the set commands out.)

The macro itself is just

  • n - search for the pattern (e.g. 'aaa')
  • wdw - your command
  • N - search backwards for the pattern (which takes us to position as the first n)
  • @q - rinse and repeat

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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