正则表达式来过滤 BBCode 列表



我正在尝试改进处理从字符串中清理BBCode的遗留PHP代码,并且目前面临列表问题。

列表的当前解决方案执行以下操作:

...
$search[]  = sprintf('~[%s](.*)[/%s]~smUi', 'list', 'list');
$search[]  = sprintf('~[%s=(.*)](.*)[/%s]~smUi', 'list', 'list');
$search[]  = sprintf('~[%s]~i', '*');
$replace[] = '$1';
$replace[] = '$2';
$replace[] = '';
...
return preg_replace($search, $replace, $string);

当字符串类似于

[list]
[*]Item 1
[*]Item 2
[*]Item 3
[/list]

但是,如果它不在列表中,它也会剥离[*]并且还会失败,例如:

[list]
[*][list]
[*]Item 1.1
[*]Item 1.2
[*]Item 1.3
[/list]
[*]Item 2
[*]Item 3
[/list]

是否可以仅使用 RegExp 来剥离[list][list=1]+[/list]标签以及[*](如果它们在列表中)?

您可以使用

$search[]  = sprintf('~[(%s)(?:=[^]]*)?]((?:(?![1b).)*?)[/1]s*~si', 'list');
$search[]  = sprintf('~[%s]~i', '\*');
$replace[] = '$2';
$replace[] = '';
$count = 0;
do {
$string = preg_replace($search, $replace, $string, -1, $count);
}
while ($count > 0);
return $string;

请参阅 PHP 演示。

我合并了前两个正则表达式,因为它们基本上匹配相同(打开标签内的=.*?部分只是可选的,我建议使用(?:=[^]]*)?匹配=然后匹配 0+ 字符,而不是]1 或 0 次。

((?:(?![1b).)*?)模式是一个经过调节的贪婪令牌,可确保匹配最内层的list标签,1此处匹配使用(%s)捕获的标签名称。

$count变量将保存用preg_replace完成的替换次数,如果没有替换任何内容,则while块退出。

最新更新