preg_replace和preg_replace_callback都不计算在内

时间:2013-11-08 14:49:56

标签: php regex preg-replace counter preg-replace-callback

function parse($string){
    $counter = 0;

    $string = preg_replace("_\[b\](.*?)\[/b\]_si", '<span class="b">'. $counter .'. $1</span>', $string, -1, $counter);

    return $string;
}

再次问好Stackoverflow!

我正在尝试创建一个ubb解析器,解析标签并将计数放在它前面:

[b]Hey[/b]
[b]Hello[/b]

应该返回:

<span class="b">1. Hey</span>
<span class="b">2. Hello</span>

但是回来了:

<span class="b">1. Hey</span>
<span class="b">1. Hello</span>

除了上面的功能之外,我还试过这个:

function parse($string){

    $counter = 0;

    $string = preg_replace_callback(("_\[b\](.*?)\[/b\]_si", function(){
        '<span class="b">'. $counter++ .'. $1</span>',
    }, $string);
}

但是,顶部的功能不起作用。我做错了什么和/或我可以试试吗?

提前致谢!

3 个答案:

答案 0 :(得分:3)

我会用一个小的类来解决它,计数器作为属性,回调是类的一个方法。

class Increaser {
    private $counter;

    public function replace($string) {
        $this->counter = 0;

        return preg_replace_callback("_\[b\](.*?)\[/b\]_si", array($this, 'createReplacement'), $string);
    }

    private function createReplacement($matches) {
        ++$this->counter;

        return '<span class="b">'. $this->counter .'. ' . $matches[1] . '</span>';
    }
}

答案 1 :(得分:0)

最终在TiMESPLiNTER的帮助下解决了它(给他信任!),不知道$1没有被带来,你必须在回调中调用变量$matches函数并获取$matches[1]而非$ 1。

$counter = 1;

function parse(){
    function cb($matches){
        global $counter;

        return '<span class="b">'. $this->counter .'. ' . $matches[1] . '</span>';
    }

    $string = preg_replace_callback("_\[b\](.*?)\[/b\]_si", 'cb', $string);
}

答案 2 :(得分:0)

您无需声明global“计数器”变量,也无需设计基于类的解决方法。您只需在preg_replace_callback()的自定义函数中使用静态变量声明即可。

代码:(Demo)-这就是我编写自己的项目的方式

$ubbText = <<<TEXT
[b]Hey[/b]
[b]Hello[/b]
TEXT;

echo preg_replace_callback(
         "~\[b](.*?)\[/b]~si",
         function ($m) {
             static $counter = 0;
             return '<span class="b">' . (++$counter) . '. ' . $m[1] . '</span>';
         },
         $ubbText
     );

或者,您可以避免使用static声明,而使用preg_replace(),因为您的代码逻辑将不可能替换替换项(无限循环是不可能的)。老实说,我不喜欢这种技术,因为它涉及迭代的preg_函数调用,该函数每次迭代进行一次替换,并且正则表达式引擎每次都需要从输入字符串的开头重新启动。

代码:(Demo

$counter = 0;
do {
    $ubbText = preg_replace(
        "~\[b](.*?)\[/b]~si",
        '<span class="b">' . (++$counter) . '. $1</span>',
         $ubbText,
         1,
         $count
     );
} while ($count);
echo $ubbText;

输出(来自两个片段):

<span class="b">1. Hey</span>
<span class="b">2. Hello</span>

p.s。我想我应该记录下来,即您的正则表达式模式不会很好地处理嵌套标签[b] bold [b]re-bold[/b][/b]的可能性。如果您的应用程序文本中无法出现这些类型的事件,则无需担心。有多种方法可以缓解此漏洞,但是在这篇文章中我不会偏离主题。如果您的应用程序需要它,请在Stack Overflow中搜索。