# change only the nth occurrence of a pattern in a string

Tim Chase python.list at tim.thechases.com
Wed Dec 31 16:48:29 CET 2008

```> I would like to change only the nth occurence of a pattern in
> a string. The problem with "replace" method of strings, and
> "re.sub" is that  we can only define the number of occurrences
> to change from the  first one.
>
>>>> v="coucou"
>>>> v.replace("o","i",2)
> 'ciuciu'
>>>> import re
>>>> re.sub( "o", "i", v,2)
> 'ciuciu'
>>>> re.sub( "o", "i", v,1)
> 'ciucou'
>
> What is the best way to change only the nth occurence
> (occurrence number n)?

Well, there are multiple ways of doing this, including munging
the regexp to skip over the first instances of a match.
Something like the following untested:

re.sub("((?:[^o]*o){2})o", r"\1i", s)

However, for a more generic solution, you could use something like

import re
class Nth(object):
def __init__(self, n_min, n_max, replacement):
#assert n_min <= n_max, \
#  "Hey, look, I don't know what I'm doing!"
if n_max > n_min:
# don't be a dope
n_min, n_max = n_max, n_min
self.n_min = n_min
self.n_max = n_max
self.replacement = replacement
self.calls = 0
def __call__(self, matchobj):
self.calls += 1
if self.n_min <= self.calls <= self.n_max:
return self.replacement
return matchobj.group(0)

s = 'coucoucoucou'
print "Initial:"
print s
print "Just positions 3-4:"
print re.sub('o', Nth(3,4,'i'), s)
for params in [
(1, 1, 'i'),  # just the 1st
(1, 2, 'i'),  # 1-2
(2, 2, 'i'),  # just the 2nd
(2, 3, 'i'),  # 2-3
(2, 4, 'i'),  # 2-4
(4, 4, 'i'),  # just the 4th
]:
print "Nth(%i, %i, %s)" % params
print re.sub('o', Nth(*params), s)

> Why this default behavior?

Can't answer that one, but with so many easy solutions, it's not
been a big concern of mine.

-tkc

```