我有多个(> 30)编译的正则表达式
regex_1 = re.compile(...)
regex_2 = re.compile(...)
#... define multiple regex's
regex_n = re.compile(...)
然后我有一个函数,它使用text
并使用上面的每个正则表达式和re.sub
方法替换它的一些单词,如下所示
def sub_func(text):
text = re.sub(regex_1, "string_1", text)
# multiple subsitutions using all regex's ...
text = re.sub(regex_n, "string_n", text)
return text
问题:是否有更有效的方法来进行这些替换?
正则表达式不能从其当前形式推广或简化。
我觉得每次正则表达式的text
的值都重新分配,因为每次重新分配时,函数只替换整个text
中的一两个字。此外,鉴于我必须为多个文档执行此操作,这会使事情进一步减慢。
提前致谢!
答案 0 :(得分:3)
在Python中重新分配值需要一段时间。与像C这样的语言不同,变量更像是一个"名称标签"。因此,更改名称标记指向的内容只需要很少的时间。
如果它们是常量字符串,我会将它们收集到一个元组中:
regexes = (
(regex_1, 'string_1'),
(regex_2, 'string_2'),
(regex_3, 'string_3'),
...
)
然后在你的函数中,只需迭代列表:
def sub_func_2(text):
for regex, sub in regexes:
text = re.sub(regex, sub, text)
return text
但是如果你的正则表达式实际上是regex_1
,regex_2
等,那么它们可能应该直接在某种列表中定义。
另请注意,如果您正在进行替换,例如'cat'
- > 'dog'
,str.replace()
方法可能更容易(text = text.replace('cat', 'dog')
),而且可能会更快。
如果您的字符串非常很长,并且使用正则表达式重新制作它可能需要很长时间。评论中提到的@Oliver Charlesworth's方法的实现可以是:
# Instead of this:
regexes = (
('1(1)', '$1i'),
('2(2)(2)', '$1a$2'),
('(3)(3)3', '$1a$2')
)
# Merge the regexes:
regex = re.compile('(1(1))|(2(2)(2))|((3)(3)3)')
substitutions = (
'{1}i', '{1}a{2}', '{1}a{2}'
)
# Keep track of how many groups are in each alternative
group_nos = (1, 2, 2)
cumulative = [1]
for i in group_nos:
cumulative.append(cumulative[-1] + i + 1)
del i
cumulative = tuple(zip(substitutions, cumulative))
def _sub_func(match):
iter_ = iter(cumulative)
for sub, x in iter_:
if match.group(x) is not None:
return sub.format(*map(match.group, range(x, next(iter_)[1])))
def sub_func(text):
return re.sub(regex, _sub_func, text)
但如果你有需要替换的重叠文本,这会破坏。
答案 1 :(得分:0)
我们可以将函数传递给re.sub
repl参数
简化为3个正则表达式以便于理解
假设regex_1,regex_2和regex_3分别为111,222和333。然后,regex_replace将是按照regex_1,regex_2和regex_3的顺序用于替换的列表保存字符串。
不确定这会改善运行时间,尝试一下
import re
regex_x = re.compile('(111)|(222)|(333)')
regex_replace = ['one', 'two', 'three']
def sub_func(text):
return re.sub(regex_x, lambda x:regex_replace[x.lastindex-1], text)
>>> sub_func('testing 111 222 333')
>>> 'testing one two three'