Bbcode 解析器无法正常工作

Bbcode parser does not work correctly

我对 BBCodes 有疑问 - 这个 preg_replace 没有按预期工作:

$message = preg_replace("/\[color=(\#[0-9A-F]{6}|[a-z]+)\](.*)\[\/color\]/Usi", "<span style=\"color:\1\">\2</span>", $message);

这可以正常工作:

[color=#ff0000]text text text text text[/color]
[color=#00ffff]texttexttext[/color]

结果:

但是如果有两个颜色标签依次出现,则无法正常工作:

[color=#ff0000][color=#00ffff]text text text text text[/color] [/color]

[color=#ff0000]text text text[color=#00ffff]text text text text text[/color] [/color]

结果:

实际上,在字符串 [color=#ff0000][color=#00ffff]text text text text text[/color] [/color] 中,您的正则表达式匹配第一个开始标签和第一个结束标签。避免这种情况的一种方法是稍微修改您的正则表达式,例如:

/\[color=(\#[0-9A-F]{6}|[a-z]+)\]([^[]*)\[\/color\]/

那么它只会匹配嵌套最多的标签。您需要在循环中执行此操作,而您的字符串包含 bbcodes。

你也可以通过 2 个替换来完成。一个用于开头,一个用于结束标记。

那些颜色标签的嵌套将不再重要。

$message = preg_replace('%\[color=(\#[0-9A-F]{6}|[a-z]+)\]%i', '<span style="color:">', $message);

$message = preg_replace('%\[/color\]%i', '</span>', $message);

或在 1 个语句中:

$message = preg_replace(
[   '%\[color=(\#[0-9A-F]{6}|[a-z]+)\]%i',
    '%\[/color\]%i'
],
[   '<span style="color:">',
    '</span>'
], $message);

正如 Casimir et Hippolyte 所指出的,不考虑嵌套可能会产生不好的结果。

所以这是另一种使用 while 循环和递归正则表达式的方法:

$pattern = '%\[color=(\#[0-9A-F]{6}|[a-z]+)\].*?(((?R)|.)*?)\[\/color\]%i';   
$replacement = '<span style="color:"></span>';

do {
    $message = preg_replace($pattern, $replacement, $message, -1, $count);
} while ($count);