0

好的,基本上我想做的是在不使用正则表达式的情况下创建一种 BB 代码系统。我在下面使用的代码似乎可以完美运行,尽管它不是。基本上,代码应该采用一个字符串并从所有 [code][/code] 块中删除所有中断标记,并将其替换回整个字符串。然后代码应该将 [code][/code] 标签转换为我正在使用的 SyntaxHighlighter 脚本的“pre”标签。

不幸的是,代码并不能完全 100% 工作。在某些情况下,它仍会将中断标记留在 [code][/code] 块内。我的代码是:

<?php
$string = "Hello\n[code]\nCode One\n[/code]\n[code]\nCode Two\n[/code]\n[code]\nCode    Three\n[/code]";
$string = nl2br($string);
$openArray = array();
$closeArray = array();
$original = "";
$newString = "";

$i = 0;
if(strpos($string, "[code]") === 0) {
    array_push($openArray, 0);
}
while($i = strpos($string, "[code]", $i + 1)) {
    array_push($openArray, $i);
}
while($i = strpos($string, "[/code]", $i + 1)) {
    array_push($closeArray, $i + 7);    
}
for($j = 0; $j < count($openArray); $j++) {
    $length = $closeArray[$j] - $openArray[$j];
    $original = substr($string, $openArray[$j], $length);
    $newString = strip_tags($original);
    $string = str_replace($original, $newString, $string);
}
$string = str_replace("[code]", '<pre class="brush: plain">', $string);
$string = str_replace("[/code]", '</pre>', $string);
echo $string;
?>

非常感谢所有答案,因为我一直想知道这有什么问题已经有一段时间了,我尝试了许多不同的方法!

4

2 回答 2

1

我在您的处理中看到的主要问题是您存储的打开和关闭标签非常独立。然后您稍后处理它们,就好像每个都属于彼此一样,但这不能保证,因为您不验证关闭代码是否遵循打开代码,如果不是两个打开或关闭代码,则应该给出解析错误。

你可以给自己写一个小辅助函数,像 strpos 一样,返回一个打开和关闭代码对的下一个位置:

function codepos($string, $code, $offset) {
    $offset = 0;
    if (FALSE === $start = strpos($string, "[$code]", $offset)) {
        return FALSE;
    }
    if (FALSE === $stop = strpos($string, "[/$code]", $start) {
        throw new Exception('Close code not found.');
    }
    if ($next = strpos($string, "[$code]", $start + 1) && $next < $stop) {
        throw new Exception('Double opening detected.');
    } 
    $pos = new stdClass;
    $pos->start = $start;
    $pos->stop = $stop;
    $pos->code = $code;
    return $pos;
}

然后更容易处理此更改,因为您已经知道事情井井有条。您可以运行 FALSE 并以不同的方式发出通知,而不是抛出异常。并且此例程尚未在第一个起始代码之前检查结束代码。

$offset = 0;
while($pos = codepos($string, 'code', $offset))
{
    ... process each code-pair.
}
于 2012-06-19T02:01:49.283 回答
0

仅用于学习或内网工具,甚至不考虑在 www 上:

您需要考虑:
行可能比字符串缓冲区长。除非您围绕它进行编码,否则您将拥有最大行大小。

打开标签之前可能的关闭标签的代码以及可能缺少的关闭/打开标签,除非您假设输入总是正确的。

能够处理以下情况:
State1 寻找一个或多个打开标签:
没有打开/关闭标签
仅打开标签
首先关闭标签 - 解析失败
一个或多个匹配的打开/关闭标签(按正确顺序)
一个或多个匹配的打开/以打开标签结尾的关闭标签(按正确顺序)
文档结束 - OK
State2 正在寻找关闭标签:
关闭标签后跟一个或多个匹配的打开/关闭标签(按正确顺序)
关闭标签后跟一个或多个匹配的打开/关闭标签(按正确顺序) 以打开标签结尾
没有关闭标签
文档结束 - 解析失败

于 2012-06-19T02:14:39.807 回答