使用正则表达式的大字符串的灾难性回溯问题



我正在尝试捕获两个字符串之间的所有内容,问题是我想要捕获的这个字符串可能长达3000行数字和逗号。因此,当这种情况发生时,我会遇到一个灾难性的回溯错误。

这是我正在使用的正则表达式,也是下面的示例数据

NEM12[sS]+?</CSVIntervalData>

<。CSVIntervalData>100,NEM12201807290900,WBAYM,EEQ2003030910307,B1E1K1Q1,03,B1,N191111580,kWh,30,30020180728,.278,.278、.278、.278、.278,.278、.278,.278,.278和.278,.056,0,0,0,0,0,0,0,0,0,,0,0,00,,0,0,00,0,0,00,074,.778,.278,278,.288,.278,900<CSVIntervalData>

注意,之间可以有一千行数字、点和逗号

您的正则表达式基于惰性匹配模式,这意味着如果需要匹配的字符串很长,正则表达式引擎会有很大的开销。当NEM12匹配时,尝试</CSVIntervalData>,一旦引擎找不到它,它就会扩展[sS]*?模式,匹配任何字符,然后再次重新测试</CSVIntervalData>模式,以此类推,您可能遇到了问题(在regex101中,您通常会看到超时问题,而不是灾难性的回溯,因为lazy模式没有回溯,只有贪婪模式才会触发回溯(。

你可以做的是打开懒惰模式:

NEM12[^<]*(?:<(?!/CSVIntervalData>)[^<]*)*</CSVIntervalData>

请参阅regex演示(注意317步与46步的区别(。

<以外的[^<]*(?:<(?!/CSVIntervalData>)[^<]*)*:0+个字符替换[sS]*?,然后用<以外的任何0+个字母替换不跟/CSVIntervalData><的任意0+序列。虽然它更长,但它可以按块匹配文本,并且在预期匹配时间较长的情况下更快、更可靠。如果文本在分隔符之间包含太多连续的<字符,则速度不会那么快,但实际数据通常不是这样。

如果您需要捕获这两个字符串NEM12</CSVIntervalData>之间的内容,请不要忘记捕获组:

NEM12([^<]*(?:<(?!/CSVIntervalData>)[^<]*)*)</CSVIntervalData>
^                                     ^    

请参阅此regex演示。

最新更新