1

preg_replace()パターンと置換が配列である場所を使用する関数があります。置換を追跡するにはカウンターが必要なので、関数をクロージャーで使用するように変換してpreg_replace_callbackいますが、コールバックに渡される一致がどのパターンに一致するかを区別する方法を見つけることができないようです。preg_replace_callback を使用して配列 => 配列の置換を行う方法はありますか?

理想的には、これは私がやりたいことですが、 $pattern と $replace は各置換の間ではなく、呼び出しに入るときに評価されるため、明らかにそうではありません

function replaceTags($text)
{
    $i = 1;

    $pattern = array(
        '/\[d\](.*?)\[\/d\]/',
        '/\[s\](.*?)\[\/s\]/',
    );

    $replace = array(
        '<div id="'.($i++).'">$1</div>',
        '<span id="'.($i++).'">$1</span>',
    );

    return preg_replace($pattern, $replace, $text);
}
4

1 に答える 1

0

私が正しく理解していれば、コールバック関数の呼び出し間で状態を維持するだけで済みます。これを行う理想的な方法は、メンバー関数を使用することです。状態はオブジェクト インスタンスに格納されます。呼び出すたびに、オブジェクトを変更して状態を変更できます。

また、コールバック内のパターンを区別するために、パターンに追加のキャプチャを追加しました。

<?php
class TagReplacer {
    private $counter = 0;

    public function replacer($matches) {
        // modify the state
        $this->counter++;

        // return the replacement text using the state
        if ($matches[1] === "d")
            $tag = 'div';
        else
            $tag = 'span';
        return "<{$tag} id=\"{$this->counter}\">{$matches[2]}</{$tag}>";
    }
}

function replaceTags($text) {
    $stateObject = new TagReplacer();
    $patterns = array(
        '/\[(d)\](.*?)\[\/d\]/',
        '/\[(s)\](.*?)\[\/s\]/',
    );

    return preg_replace_callback(
            $patterns,
            array(&$stateObject, "replacer"),
            $text);
}

echo replaceTags("zzz[d]123[/d]zzz[s]456[/s]zzz[d]78[/d]zzz[s]90[/s]zzz");
?>

出力は

zzz<div id="1">123</div>zzz<span id="3">456</span>zzz<div id="2">78</div>zzz<span id="4">90</span>zzz

ID が番号順に並んでいないことに驚きました。私の推測では、preg_replace_callback はパターン配列を繰り返し処理し、パターンごとに一度にすべての置換を行っています。

于 2012-07-18T03:01:00.263 に答える