如果不合适,多行捕获正则表达式会失败

时间:2014-11-07 07:43:33

标签: regex

我想从xml文件中检索数据。我使用像这样的正则表达式:

/
<OVERLAYLINKPROJECT(?:.|\s)+
<OUTPUT
/xU

这是我的xml文件的摘录:

<OVERLAYLINKPROJECT id='0773C138' parent_id='007285A0' ovl_id='0x4b' run_address='0x9022a' run_size='0x450' live_address='0x40c111' live_size='0x678' >
<FILE_NAME><![CDATA[xxx.ovl]]></FILE_NAME>
<OUTPUT_SECTIONS>
<OUTPUT_SECTION id='0773C138' name='xxxx' type='SHT_PROGBITS' start_address='0x9022a' word_size='0x450' word_size_unmapped='0x0' in_overlay='' >
<INPUT_SECTIONS>
<INPUT_SECTION id='0580D5B0' name='yyyy' start_address='0x9022b' size='0x44f' element_at='0x0' >

正则表达式在没有ungreedy修饰符U的情况下不起作用。为什么呢?

2 个答案:

答案 0 :(得分:2)

令人惊讶的是,问题是catastrophic backtracking

您使用了(?:.|\s),大概是因为.不匹配换行符,而您的输入包含它们。但是,\s也匹配其他空格,也可以由.匹配。

如果您不使用ungreedy修饰符,(?:.|\s)+首先匹配<OVERLAYLINKPROJECT后的整个字符串,然后回溯以查看<OUTPUT首先匹配的位置。在每个空间,它需要尝试将其与.匹配或与\s匹配之前的所有备选方案,然后才能确保它们都不会导致有效匹配。

字符串的那一部分有14个空格。每一个都必须与所有其他组合进行检查,结果为14! (= 87178291200)所有必须检查的排列。这需要一段时间(或正则表达式引擎超时)。

当您使用ungreedy修饰符时,正则表达式引擎会逐步匹配一个字符,&#34;标记&#34;每个空格用于以后评估,以防匹配失败 - 但只要遇到<OUTPUT就会成功。这就是为什么它匹配得更快。如果输入字符串包含<OUTPUT,它仍然会灾难性地失败 - 因为在这种情况下,正则表达式引擎需要重新访问所有空格并尝试不同的排列,这是徒劳的希望找到匹配的方式。

使用/s修饰符来允许点匹配换行符:

/
<OVERLAYLINKPROJECT.+
<OUTPUT
/xs

答案 1 :(得分:0)

<OVERLAYLINKPROJECT(?:.|\s)+?<OUTPUT

试试这个。看看演示。

http://regex101.com/r/bW3aR1/1

正如蒂姆所解释的那样,你的正则表达式的问题是灾难性的回溯。