views:

84

answers:

3

I saw other questions dealing with the finding the n-th occurrence of a word/pattern, but I couldn't find how you would actually substitute the n-th occurrence of a pattern in vim. There's the obvious way of hard coding all the occurrences like

:s/.*\(word\).*\(word\).*\(word\).*/.*\1.*\2.*newWord.*/g 

Is there a better way of doing this?

A: 

Well, if you do /gc then you can count the number of times it asks you for confirmation, and go ahead with the replacement when you get to the nth :D

kprobst
Yup, but I want to substitute the n-th occurrence without the confirmation (like if I had to write a script to do it).
Gaurav Dadhania
+1  A: 

You can do this a little more simply by using multiple searches. The empty pattern in the :s/pattern/repl/ command means replace the most recent search result.

:/word//word//word/ s//newWord/
or
:/word//word/ s/word/newWord/

You could then repeat this multiple times by doing @:, or even 10@: to repeat the command 10 more times.

Alternatively, if I were doing this interactively I would do something like:

3/word
:s//newWord/r

That would find the third occurrence of word and then perform a substitution.

John Kugelman
Hrm, there are still a number of problems with this, if the first word is the word we're looking for, '3/word' will get us to the 4th occurrence. Also, when I tried the substitution after finding the n-th instance, it still substitutes the first occurrence.
Gaurav Dadhania
Oops, yes, the `:s` needs the `r` flag.
John Kugelman
`3/word` will find the third occurrence starting at the cursor. Go to the top of the file with `gg` if you want to start there. Note that `3/word` is equivalent to typing `/word` three times so it definitely finds the third occurrence.
John Kugelman
-1: Neither of these work for me if all the words are on the same line (which is what I assume the OP means). In both examples the substitution still happens to the first word on the line.
Dave Kirby
+1  A: 

For information,

s/\%(\(pattern\).\{-}\)\{41}\zs\1/2/

also works to replace 42th occurrence. However, I prefer the solution given by John Kugelman which is more simple -- even if it will not limit itself to the current line.

Luc Hermitte