【发布时间】:2009-11-12 14:11:18
【问题描述】:
为什么会出现以下段错误,我该如何预防?
<?php
$str = ' <fieldset> <label for="go-to">Go to: </label> '
. str_repeat(' ', 10000)
. '<input type="submit" value="Go" /> </fieldset> </form>';
preg_match_all("@
</?(?![bisa]\b)(?!em\b)[^>]*> # starting tag, must not be one of several inline tags
(?:[^<]|</?(?:(?:[bisau]|em|strong|sup)\b)[^>]*>)* #allow text and some inline tags
[\?\!\.]+
@ix", $str, $matches);
?>
我相信它会导致 .... 等待它 .... 堆栈溢出。
编辑:
以上是演示问题的模式的简化版本。更完整的版本:
@
</?(?![bisa]\b)(?!em\b)[^>]*> # starting tag, must not be one of several inline tags
(?:[^<]|</?(?:(?:[bisau]|em|strong|sup)\b)[^>]*>)* # continue, allow text content and some inline tags
# normal sentence ending
[\?\!\.]+ # valid ending characters -- note elipses allowed
(?<!\b[ap]m\.)(?<!\b[ap]\.m\.)(?<!digg this\!)(?<!Stumble This\!) # disallow some false positives that we don't care about
\s*
(?:'|&\#0*34;|'|‘)?\s* # closing single quotes, in the unusual case like "he said: 'go away'".
(?:"|"|&\#0*34;|&\#x0*22;|”|&\#0*8221;|&\#x0*201D;|''|``|\xe2\x80\x9d|&\#0*148;|&\#x0*94;|\x94|\))?\s* # followed by any kind of close-quote char
(?=\<) # should be followed by a tag.
@ix
目的是找到似乎以有效英文句子结尾结尾的 html 块。我发现这种方法非常擅长区分“内容”文本(如文章正文)和“布局”文本(即导航元素)。但是,有时如果标签之间有大量空白,它就会爆炸。
【问题讨论】:
-
有趣 - 我也可以重现崩溃。我建议你解构正则表达式,取出元素直到它停止崩溃。然后看看您是否可以获取触发崩溃的元素并创建最简单的段错误示例,并将其记录在 bugs.php.net
-
我认为这不是正则表达式引擎的错误。我只是认为你正在让它建立一个巨大的堆栈来处理回溯。也许如果你能解释你想要捕捉什么,我们可以建议一个替代正则表达式,减少回溯。
-
如您所见,正则表达式并不是万能的工具。最好使用一个简单的解析器来读取你的标记结构,看看你有什么标签/元素。
-
''有些人在遇到正则表达式时会想“我知道,我会使用我记得的朗朗上口的引语”。现在他们没有在讨论中添加任何内容。''
-- Tomalak
标签: php regex stack-overflow pcre