preg_replace_callback with array pattern and replacement

梦想与她 提交于 2019-12-13 06:15:18

问题


I have a function which uses preg_replace() where the pattern and replacements are arrays. I need a counter to track the replacements, so I am converting the function to use preg_replace_callback with a closure, but I can't seem to find a way to distinguish which pattern the match being passed to the callback matches. Is there a way to do array => array replacement using preg_replace_callback?

Ideally this is what I'd like to work, but obviously it won't since $pattern and $replace are evaluated going into the call and not inbetween each replacement

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);
}

回答1:


If I understand it correctly, you just need to maintain state between calls to your callback function. The ideal way to do this is using a member function. The state is stored in the object instance. Each time you call, you can modify the object, changing your state.

I also added an extra capture to your patterns in order to differentiate between the patterns in the callback.

<?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");
?>

The output is

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

I was surprised that the ids are not in numerical order. My guess is that preg_replace_callback iterates through the pattern array doing all the replacements at once for each pattern.



来源:https://stackoverflow.com/questions/11533175/preg-replace-callback-with-array-pattern-and-replacement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!