2

次のセグメンテーション違反が発生するのはなぜですか。また、どうすればそれを防ぐことができますか?

<?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*
(?:&apos;|&\#0*34;|'|&lsquo;)?\s* # closing single quotes, in the unusual case like "he said: 'go away'".
(?:"|&quot;|&\#0*34;|&\#x0*22;|&rdquo;|&\#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ブロックを見つけることです。この方法は、「コンテンツ」テキスト(記事の本文など)と「レイアウト」テキスト(ナビゲーション要素など)の違いを区別するのに非常に優れていることがわかりました。ただし、タグの間に大量の空白があると、爆発することがあります。

4

4 に答える 4

2

私が最初に試みることは、すべての数量詞を所有格にし、すべてのグループをアトミックにすることです。

"@</?+(?![bisa]\b)(?!em\b)[^>]*+>
(?>[^<]++|</?+(?>(?>[bisau]|em|strong|sup)\b)[^>]*+>)*+
[?!.]+
@ix"

ジェレミーの言う通りだと思います。バックトラック自体があなたを殺しているのではなく、バックトラックを可能にするために正規表現エンジンが保存しなければならないすべての状態情報です。正規表現は、バックトラックする必要がある場合でも、とにかく失敗するように構成されているようです。したがって、所有格の数量詞とアトミックグループを使用し、無駄な情報をわざわざ保存しないでください。

編集:文末の句読点を許可するために、2行目に別の代替手段を追加できます:

(?>[^<?!.]++|(?![^?!.\s<]++<)[?!.]++|</?+(?>(?>[bisau]|em|strong|sup)\b)[^>]*+>)*+

加算は、要素内の最後の非空白文字でない限り、上記の1つ以上の文字と一致します。

于 2009-11-12T16:06:54.207 に答える
1

PHPの新しいバージョンでも、既知のセグメント障害の問題があるPCRE7.0にバンドルされていると確信しています。技術的にはPCREの問題であり、PHPの問題ではないため、この問題を修正する意図はないと思います。

あなたが最善の策を成し遂げようとしていることを私たちに話したら、別の表現を書こうとすることでしょう。

問題のバグは次のとおりです: http://bugs.php.net/bug.php? id = 40909

于 2009-11-12T16:20:50.733 に答える
0

これはまだあなたが望むことをしますか?

</?(?![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
[\?\!\.]+
于 2009-11-12T14:44:03.503 に答える
0

あなたの正規表現は大量のバックトラックを引き起こします。真ん中に10000文字あると、かなり乱雑で遅くなります。それでも、クラッシュするとは思わない...!

于 2009-11-12T14:52:33.267 に答える