匹配内重复匹配

Repeated match inside match

   $regex = '/\[b\](.*?)\[\/b\]/is';

   $string = '[b][b][b]string[/b][/b][/b]';

这只会匹配到第一个 [/b],所以如果我使用此正则表达式将此 bbcode 转换为 HTML,我将得到以下结果:

string[/b][/b]

我正在使用 PHP preg_replace,我怎么可以只用 string,所以 3 html 个粗体标签。

您可以使用非捕获组来扩展重复计数:

(?:\[b\])+(.*?)(?:\[\/b\])+
^^^     ^^     ^^^       ^^

demo

对于这种肮脏的情况:

this [b]is [b]a[/b][/b] test [b]string[/b]

递归解决方案有效:

\[b](?:(?:(?!\[b]).)*?|(?R))*\[/b]

Live demo

PHP代码:

$str = 'this [b]is [b]a[/b][/b] test [b]string[/b]';

echo preg_replace_callback('~\[(\w+)](?:(?:(?!\[]).)*?|(?R))*\[/()]~', function($m) {
    return "**".preg_replace("~\[/?$m[1]]~", '', $m[0])."**";
}, $str);

输出:

this **is a** test **string**