如何替换第N个出现的目标?(Python)
我想要在一堆东西里替换第N次出现的某个词。我的想法是用re.sub()这个方法来实现,但我找不到合适的正则表达式来解决这个问题。我试着参考了这个链接:http://docstore.mik.ua/orelly/perl/cookbook/ch06_06.htm,但是在处理多行文本时遇到了困难。
我现在的方法是一个逐步查找的方式,每次替换后从头开始找到每个出现的位置。这样做效率不高,我想听听大家的建议。谢谢!
6 个回答
2
类似这样的正则表达式应该能帮到你。不过我不太确定它的效率如何:
#N=3
re.sub(
r'^((?:.*?mytexttoreplace){2}.*?)mytexttoreplace',
'\1yourreplacementtext.',
'mystring',
flags=re.DOTALL
)
这里的DOTALL标志是很重要的。
3
我想你是指 re.sub
。你可以传递一个函数,并记录它被调用了多少次:
def replaceNthWith(n, replacement):
def replace(match, c=[0]):
c[0] += 1
return replacement if c[0] == n else match.group(0)
return replace
用法:
re.sub(pattern, replaceNthWith(n, replacement), str)
不过这种方法感觉有点不太正规,也许还有更优雅的解决办法。
1
我之前一直在为这个问题苦恼,但我找到了一种我认为很“python风”的解决方案:
>>> def nth_matcher(n, replacement):
... def alternate(n):
... i=0
... while True:
... i += 1
... yield i%n == 0
... gen = alternate(n)
... def match(m):
... replace = gen.next()
... if replace:
... return replacement
... else:
... return m.group(0)
... return match
...
...
>>> re.sub("([0-9])", nth_matcher(3, "X"), "1234567890")
'12X45X78X0'
编辑:这个匹配器由两个部分组成:
alternate(n)
函数。这个函数会返回一个无限的真假序列,每隔第 n 个值是 True。可以把它想象成list(alternate(3)) == [False, False, True, False, False, True, False, ...]
,也就是说每三个值中有一个是 True。match(m)
函数。这个函数会传递给re.sub
:它会获取alternate(n)
中的下一个值 (gen.next()
),如果这个值是True
,那么就替换掉匹配到的值;如果不是,就保持原样(用它自己替换)。
我希望这个解释足够清楚。如果我的解释不够明了,请告诉我,我会改进的。