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 回答