【发布时间】:2020-04-13 13:32:25
【问题描述】:
我需要替换每个模式,例如:{foo} 替换为 FOO + 一个不断增加的数字,并且还需要为每个匹配替换 do_something_else(...)。示例:
'hell{o} this {is} a t{est}' => hellO1 this IS2 a tEST3
如何不使用替换函数,而只使用匹配循环?我正在寻找类似的东西:
import re
def do_something_else(x, y): # dummy function
return None, None
def main(s):
i = 0
a, b = 0, 0
for m in re.findall(r"{([^{}]+)}", s): # loop over matches, can we
i += 1 # do the replacement DIRECTLY IN THIS LOOP?
new = m.upper() + str(i)
print(new)
s = s.replace('{' + m + '}', new) # BAD here because: 1) s.replace is not ok! bug if "m" is here mutliple times
# 2) modifying s while looping on f(.., s) is probably not good
a, b = do_something_else(a, b)
return s
main('hell{o} this {is} a t{est}') # hellO1 this IS2 a tEST3
下面的代码(with 一个替换函数)可以工作,但是这里使用全局变量是一个大问题,因为实际上do_something_else() 可能需要几毫秒,而且这个过程可能会混合与main() 的另一个并发运行:
import re
def replace(m):
global i, a, b
a, b = do_something_else(a, b)
i += 1
return m.group(1).upper() + str(i)
def main(s):
global i, a, b
i = 0
a, b = 0, 0
return re.sub(r"{([^{}]+)}", replace, s)
main('hell{o} this {is} a t{est}')
【问题讨论】:
-
您要匹配的确切目标文本是什么,替换的内容是什么?
-
re.findall用于提取匹配项,而不是修改它们。至于str.replace,它经常在循环中使用,仅替换第一次出现的s = s.replace('{' + m + '}', new, 1)。 -
字符串在 Python 中是不可变的。所以重新分配
s并不重要。findall仍在对原始字符串进行迭代。