1
$regex = '#<p.+</p>#s';

私の目的は、最初の段落タグと最後の段落タグの間にある大きな文字列を返すことです。これは、他の段落も含め、すべてを含めることです。

上記の正規表現は、段落タグを除くすべてに対して機能します。「p」を「html」に置き換えてテストし、成功を返し、「スクリプト」に置き換えて成功を返しました...これらのケースではtrueを返すのに、段落ではtrueを返さないのはなぜですか?

私はまだこれに取り組んでおり、正規表現を停止させる奇妙なエスケープシーケンスはないと比較的確信しています...最初と最後の「html」タグの間のすべてを抽出できるため、これだと思います。「html」タグ間のテキストには、抽出に失敗したすべての「p」タグも含まれています。何らかのエスケープやエラーがあった場合、「html」タグの抽出時にも同じエラーがスローされると思います。preg_quote() を試しましたが成功しませんでした。

おそらく、ドキュメント全体を処理できるように、正規表現処理専用のメモリを高く設定する必要がありますか?

更新: ほとんどの場合、先頭の 'p' は (ほとんどの場合) 同じ段落タグの終了 '/p' タグではありません。

更新: 返される結果は次のようなものになります。

<p>this is the first tag</p>this is a bunch of text from the document, could be all manner of tags <p>this is the last paragraph tag</p>

更新: コード例

$htmlArticle = <<< 'ENDOFHTML'

Insert data from pastebin here
http://pastebin.com/4A3FYGc8

ENDOFHTML;

$pattern = '#<html.+/html>#s'; // Works fine, returns all characters between first <html and last /html
$pattern = '#<script.+/script>#s'; // Works fine, same as above
$pattern = '#<p.+/p>#s'; // Returns nothing, nothing at all. :'(

preg_match($pattern, $htmlArticle, $matches);

var_dump($matches);

?>

解決策: ini_set('pcre.backtrack_limit', '1000000');

バックトラックの制限を使い果たしました。これは php.ini ファイルの設定であり、ini_set() を使用してコードで設定できます。不思議なことに、php.ini ファイルの値と一致するように ini_set() を使用して値を設定しました...最初から機能していたはずです。--- 解決策を投稿でき次第、よろしくお願いします。

4

2 に答える 2

0

それは非常に興味深いです。エラーは返されません。短いドキュメントを使用すると、一致が返されるようです。なぜこれが起こるのか理解できません。膨大なドキュメントに問題なく正規表現を使用しました。

これにより一致が生成されることに注意してください。#<p\b.+<\#s

試合がたくさんあるので、おそらくバックトラック制限で遊んでみてください</p>。ただし、制限が低すぎる場合は、0ではなくpreg_matchを返すことを期待します。False

回避策として、代わりにこれを試してください。

function extractBetweenPs($data) {
$startoffset = null;
$endoffset = null;
if (preg_match('/<p\b/', $data, $matches, PREG_OFFSET_CAPTURE)) {
    $startoffset = $matches[0][1];
    $needle = '</p>';
    $endoffset = strrpos($data, $needle);
    if ($endoffset !== FALSE) {
        $endoffset += strlen($needle);
    } else {
        // this will return everything from '<p' to the end of the doc
        // if there is no '</p>'
        // maybe not what you want?
        $endoffset = strlen($data);
    }
    return substr($data, $startoffset, $endoffset-$startoffset);
}
return '';
}

とはいえ、これは非常に奇妙な要件です。構造化されたドキュメントの任意のセクションをブロブとして扱うことです。たぶん、あなたは一歩下がって、あなたのより広い目標が何であるかを言うことができます、そして私たちは別のアプローチを提案することができますか?

于 2012-08-18T19:43:47.220 に答える
-1

正規表現は、HTML を正しく解析するために使用できるツールではありません。

必要なのはDOMDocumentだけです

$dom = new DOMDocument();
$dom->loadHTML($your_html);
$node = $dom->getElementsByTagName('p')->item(0);
$dom2 = new DOMDocument();
$node = $dom2->importNode($node, true);
$dom2->appendChild($node);
echo $dom2->saveHTML();
于 2012-08-18T18:47:46.927 に答える