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

我正在尝试制作一个 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);
}

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

4

3 回答 3

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>';
    }
}
于 2013-11-08T14:53:42.507 回答
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);
}
于 2013-11-08T15:10:36.197 回答
0

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

代码:(演示)——这是我编写自己项目的方式

$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_函数调用,每次迭代都会进行一次替换,并且正则表达式引擎每次都需要从输入字符串的开头重新启动。

代码:(演示

$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>

ps 我想我应该声明您的正则表达式模式不会有利地处理嵌套标签的可能性[b] bold [b]re-bold[/b][/b]。如果您的应用程序文本中不可能出现这些类型的情况,那么不用担心。有一些方法可以缓解这个漏洞,但我不会在这篇文章中离题。如果您的应用程序需要,请在 Stack Overflow 上搜索。

于 2020-11-23T07:43:30.000 回答