如何替换第N个出现的目标?(Python)

2 投票
6 回答
1532 浏览
提问于 2025-04-17 00:18

我想要在一堆东西里替换第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'

编辑:这个匹配器由两个部分组成:

  1. alternate(n) 函数。这个函数会返回一个无限的真假序列,每隔第 n 个值是 True。可以把它想象成 list(alternate(3)) == [False, False, True, False, False, True, False, ...],也就是说每三个值中有一个是 True。

  2. match(m) 函数。这个函数会传递给 re.sub:它会获取 alternate(n) 中的下一个值 (gen.next()),如果这个值是 True,那么就替换掉匹配到的值;如果不是,就保持原样(用它自己替换)。

我希望这个解释足够清楚。如果我的解释不够明了,请告诉我,我会改进的。

撰写回答