我尝试在一个巨大的文本文件中使用正则表达式进行一些替换,如下所示:
repeatedPtn_1=r'[^{}]*(?:{{[^{}]*}})*[^{}]*'
repeatedPtn_2=r'[^{}]*(?:{{[^{}]*}})*[^{}]*(?:{{[^{}]*}})*[^{}]*'
pattern=r'{{\s* RQ:'+repeatedPtn_1+r'(?:passage|text|quote)\s*=('+repeatedPtn_1+r')}}'
out_text=re.sub(pattern, r'{{quote-Temple:\1}}', out_text, flags=re.DOTALL|re.IGNORECASE)
因此,如果我在模式中使用repeatedPtn_1
,我会在不到10分钟的时间内得到结果,但是如果我使用最适合我的repeatedPtn_2
,我的笔记本电脑会持续运行几个小时而没有完成!
有人能告诉我为什么吗?并帮助我找到解决方案。
1条答案
按热度按时间pftdvrlh1#
第二个子模式(当放置在最终正则表达式中时):
当它无法匹配长输入时会遇到麻烦(例如,其中只有一个大括号,而不是双括号,并且其中单个大括号在输入中出现 far):它将回溯以检查在第一个
[^{}]*
中匹配的少一个字符,以及在中间[^{}]*
中匹配的少一个字符,...等等,导致[^{}]*
模式的左、中、右出现的尺寸的笛卡尔积。这是“灾难性回溯”,如this test on regex101所示:我在RQ:
和passenger
之间嵌入了模式,并提供了一段具有RQ:
前缀但没有passenger
后缀的输入。要解决这个问题,请确保这些左、中、右子模式永远不会匹配相邻的字符。换句话说,
(?:{{[^{}]*}})
必须至少匹配一次。如果这是不可能的,下一个[^{}]*
甚至不应该被考虑。所以:
参见here,使用此更新的正则表达式进行相同的测试。