PHP编辑中间的字符串不起作用?

时间:2012-06-19 01:08:14

标签: php string parsing scripting

好吧,基本上我要做的是创建一种不使用正则表达式的BB Code系统。我在下面使用的代码似乎可以完美地工作,尽管它不是。基本上,代码应该接受一个字符串并从所有[code] [/ code]块中删除所有break标记,并将其替换回整个字符串。然后代码应该将[code] [/ code]标签变成我正在使用的SyntaxHighlighter脚本的“pre”标签。

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

<?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;
?>

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

2 个答案:

答案 0 :(得分:1)

我看到你处理的主要问题是你将open和close标签存储起来非常独立。然后你处理它们就好像每个人都属于彼此一样,但这并不能保证,因为你没有验证结束代码是否跟在开始代码之后,如果不是两个打开或关闭代码,那么应该给出一个解析错误。

你可以写一个小帮手函数,就像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.
}

答案 1 :(得分:0)

仅限学习或内联网工具,甚至不在www:
上考虑
你需要考虑:
行可能比字符串缓冲区长。知道你将拥有最大线路大小,除非你围绕它进行编码
除非您认为输入始终是正确的,否则在打开标签和可能缺少的关闭/打开标签之前可能关闭标签的代码
能够处理以下情况:
State1寻找一个或多个开放标签:
没有打开/关闭标签
仅打开标签
首先关闭标签 - 解析失败
一个或多个匹配的打开/关闭标签(按正确顺序)
一个或多个匹配的打开/关闭标签(按正确顺序)以打开标签结束 文件结束 - 确定
State2寻找关闭标签:
close标签后跟一个或多个匹配的打开/关闭标签(按正确顺序)
close标签后跟一个或多个匹配的打开/关闭标签(按正确顺序),以打开标签结束 没有关闭标签
文件结束 - 解析失败