我正在尝试捕获两个字符串之间的所有内容,问题是我想要捕获的这个字符串可能长达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演示。