regex 执行命令的时间

smdncfj3  于 2023-10-22  发布在  其他
关注(0)|答案(1)|浏览(112)

我尝试在一个巨大的文本文件中使用正则表达式进行一些替换,如下所示:

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,我的笔记本电脑会持续运行几个小时而没有完成!
有人能告诉我为什么吗?并帮助我找到解决方案。

pftdvrlh

pftdvrlh1#

第二个子模式(当放置在最终正则表达式中时):

[^{}]*(?:{{[^{}]*}})*[^{}]*(?:{{[^{}]*}})*[^{}]*

当它无法匹配长输入时会遇到麻烦(例如,其中只有一个大括号,而不是双括号,并且其中单个大括号在输入中出现 far):它将回溯以检查在第一个[^{}]*中匹配的少一个字符,以及在中间[^{}]*中匹配的少一个字符,...等等,导致[^{}]*模式的左、中、右出现的尺寸的笛卡尔积。这是“灾难性回溯”,如this test on regex101所示:我在RQ:passenger之间嵌入了模式,并提供了一段具有RQ:前缀但没有passenger后缀的输入。
要解决这个问题,请确保这些左、中、右子模式永远不会匹配相邻的字符。换句话说,(?:{{[^{}]*}})必须至少匹配一次。如果这是不可能的,下一个[^{}]*甚至不应该被考虑。
所以:

[^{}]*(?:(?:{{[^{}]*}})+[^{}]*){0,2}

参见here,使用此更新的正则表达式进行相同的测试。

相关问题