2

PHP と正規表現に関してはまったく無知ですが、フォーラムの壊れたプラグインを修正しようとしています。

以下を交換したいと思います。

<blockquote rel="blah">foo</blockquote>

<blockquote class="a"><div class="b">blah</div><div class="c"><p>foo</p></div></blockquote>

実際、その部分は簡単で、これを行うためにプラグインを部分的に修正しました。次の正規表現はpreg_replace_callback()、置換を行うための呼び出しで使用されています。

/(<blockquote rel="([\d\w_ ]{3,30})">)(.*)(<\/blockquote>)/u

コールバック コードは次のとおりです。

return <<<BLOCKQUOTE
<blockquote class="a"><div class="b">{$Matches[2]}</div><div class="c"><p>{$Matches[3]}</p></div></blockquote>
BLOCKQUOTE;

そして、それは上記の例(ネストされていないブロック引用)で機能します。ただし、次の例のようにブロック引用符がネストされている場合:

<blockquote rel="blah">foo <blockquote rel="bloop">bar ...maybe another nest...</blockquote></blockquote>

うまくいきません。私の質問は、正規表現/PHP の組み合わせを使用して、ネストされたすべての引用符を置き換えるにはどうすればよいですか? PHPで再帰パターンが可能であることは知ってい(?R)ます; 次の正規表現は、ネストされたすべての引用符を含む文字列からそれらを抽出します。

/(<blockquote rel="([\d\w_ ]{3,30})">)(.*|(?R))(<\/blockquote>)/s

preg_replace_callback()しかし、そこから先は、ネストされた各ブロック引用を上記の置換で置き換えるためにコールバックで何をすべきかよくわかりません。

どんな助けでも大歓迎です。

4

2 に答える 2

6

簡単な答えは、正規表現ではこれを行うことができないということです。任意の深さのネストされたタグ (または括弧、大括弧など) の言語は規則的ではないため、正規表現と一致させることはできません。DOM パーサーを使用するか、何らかの奇妙な理由で絶対に必要な場合は、独自の解析スキームを作成することをお勧めします。

複雑な答えは、本当に醜いハックな正規表現と PHP コードでこれを行うことができるかもしれないということですが、正直に言うと、私はそれをお勧めしません。

参照:チョムスキー階層.

以下も参照してください。

于 2010-10-17T01:37:22.363 に答える
0

再帰的な置換は直接サポートされてpreg_replace_callback()おらず、この場合は特に役に立ちません。しかし、複数のパスで置換を行うことを止めるものは何もありません。最初のパスは最も外側のタグを処理し、後続のパスは内側に向かって処理します。オプションの$count引数は、各パスで実行された置換の数を示します。ゼロになったら完了です。

$regex = '~(<BQ rel="([^"]++)">)((?:(?:(?!</?+BQ\b).)++|(?R))*+)(</BQ>)~s';
$sub = '<BQ class="a"><div class="b">$2</div><div class="c"><p>$3</p></div></BQ>';
do {
  $s = preg_replace($regex, $sub, $s, -1, $count);
} while ($count != 0);

ideone.com で実際の動作をご覧ください

于 2010-10-17T03:59:22.480 に答える