如何在PHP中用preg_replace处理UBB代码时跳过[code]标签内容?
解决UBB解析中[code]块不被干扰的PHP方案
直接用「占位符替换法」是最稳妥的,完美避开正则嵌套冲突,还能兼容未闭合的[code]标签,步骤如下:
具体实现步骤
- 提取所有[code]块并占位
先把文本里所有的[code]...[/code](包括未闭合的,比如到文本结尾的内容)提取出来,用唯一占位符替换掉这些块,同时把提取的内容暂存到数组里。 - 处理其他UBB标签
对替换后的文本正常处理其他UBB规则(比如[b]转、[i]转、换行转
等),这时候完全不用担心影响code块内容。 - 还原[code]块并转换为HTML
把占位符替换回原来的code内容,同时将[code]/[/code]标签转换成对应的HTML代码,还要对code内容做HTML转义,防止XSS并保证原样显示。
完整代码示例
function parse_ubb($text) { // 1. 提取所有code块(支持未闭合的情况) $code_blocks = []; // 正则匹配[code]开始到[/code]结束,或者到文本结尾 $text = preg_replace_callback('/\[code\](.*?)(\[\/code\]|$)/s', function($matches) use (&$code_blocks) { $index = count($code_blocks); $code_content = isset($matches[1]) ? $matches[1] : ''; $code_blocks[$index] = $code_content; // 返回唯一占位符 return "__CODE_BLOCK_{$index}__"; }, $text); // 2. 处理其他UBB标签(这里示例几个常用的,可根据自身规则扩展) $ubb_rules = [ '/\[b\](.*?)\[\/b\]/s' => '<strong>$1</strong>', '/\[i\](.*?)\[\/i\]/s' => '<em>$1</em>', '/\[u\](.*?)\[\/u\]/s' => '<u>$1</u>', '/\n/' => '<br>', // 其他UBB规则... ]; foreach ($ubb_rules as $pattern => $replacement) { $text = preg_replace($pattern, $replacement, $text); } // 3. 还原code块,转换为HTML的pre+code标签,同时转义内容 foreach ($code_blocks as $index => $content) { // 转义HTML特殊字符,保证代码原样显示 $escaped_content = htmlspecialchars($content, ENT_QUOTES); $text = str_replace("__CODE_BLOCK_{$index}__", "<pre><code>{$escaped_content}</code></pre>", $text); } return $text; } // 测试示例 $test_text = "这是[b]加粗[/b]文本\n[code]这里是代码,包含[b]、<br>等标签[/code]\n还有未闭合的[code]这部分是未闭合的代码"; echo parse_ubb($test_text);
方案优势
- 彻底隔离code块和其他UBB规则,不会出现code内被误替换的情况;
- 自动处理未闭合的[code]标签,不会导致页面错乱;
- 逻辑清晰,比复杂的(*SKIP)(*FAIL)正则更容易维护和扩展;
- 对code内容做HTML转义,避免XSS风险,同时保证代码原样显示。
内容的提问来源于stack exchange,提问作者freakulum
相关产品推荐
相关产品推荐

