PHP preg_replace_callback 替换错误的开始和结束标签

问题描述 投票:0回答:1

我的 BB 代码功能有问题。我已经测试了以下输入来替换:

Testtext! <b>text<u>testtext</u>test</b><b>test</b>

并得到这个(混合)输出:

Testtext! [b]text[u]testtext[/u]test</b>test<b>test[/b]

我的 PHP 代码:

function html_to_bbcode($input) {
$regex[] = '#\<b>((?:[^[]|\<(?!/?b>)|(?R))+)\</b>#im';
$regex[] = '#\<i>((?:[^[]|\<(?!/?i>)|(?R))+)\</i>#im';
$regex[] = '#\<u>((?:[^[]|\<(?!/?u>)|(?R))+)\</u>#im';

if (is_array($input)) {
    $tag = explode('>', $input[0]);
    $tag = str_replace('<', '', $tag[0]);
if ($tag == 'b') {
    $input = '[b]'.$input[1].'[/b]';
} else if ($tag == 'i') {
    $input = '[i]'.$input[1].'[/i]';
} else if ($tag == 'u') {
    $input = '[u]'.$input[1].'[/u]';
}
}
return preg_replace_callback($regex, 'html_to_bbcode', $input);
}

(以及更多标签)

我找不到那个错误:(有人能解决这个问题吗?

preg-replace
1个回答
0
投票

首先,作为最佳实践,您可能不应该首先尝试使用正则表达式解析 HTML(但如果不能保证这是有效的 HTML,因为它来自不可信的来源,例如最终用户,那么……也许)。 有些 BBCode 库可能会有所帮助,但我个人没有任何使用它们的经验。

其次,当您从最外层的配对标签开始工作时,递归正则表达式模式可能是一个好主意。在这种情况下,在我看来,您打算从最内层的配对标签开始工作。

如果您要继续使用正则表达式,那么我可能会对以下循环

preg_replace()
脚本感兴趣。 演示

$text = <<<TEXT
Testtext! <b>text<u>testtext</u>test</b><b>test</b>
TEXT;

do {
    $text = preg_replace(
        '#<([biu])>((?:(?!</?(?1)>).)+)</\1>#i',
        '[$1]$2[/$1]',
        $text,
        -1,
        $count
    );
} while ($count);
echo $text;
// Testtext! [b]text[u]testtext[/u]test[/b][b]test[/b]

这将替换最里面的标签对(不会被任何其他指定标签打断),直到完成所有可能的替换。

© www.soinside.com 2019 - 2024. All rights reserved.