5

我在一个用 PHP 编写的网站上为我自己的个人论坛编写了一个 Quote 函数。

消息引用的标签看起来像[quote=username]message[/quote],所以我写了这个函数:

$str=preg_replace('#\[quote=(.*?)\](.*?)\[/quote\]#is', '<div class="messageQuoted"><i><a href="index.php?explore=userview&userv=$1">$1</a> wrote :</i>$2</div>', $str);

如果报价为一,则此方法有效,但随后用户引用报价,则无效。所以我需要一种递归引用来应用这种行为。

我试图搜索这么多主题,但我真的不明白它是如何工作的。对于进行此类操作的任何建议/提示,我们将不胜感激!让我知道,谢谢!

编辑

最后,这是我自己的解决方案:

if(preg_match_all('#\[quote=(.*?)\](.*?)#is', $str, $matches)==preg_match_all('#\[/quote\]#is', $str, $matches)) {
    array_push($format_search, '#\[quote=(.*?)\](.*?)#is');
    array_push($format_search, '#\[/quote\]#is');

    array_push($format_replace, '<div class="messageQuoted"><a class="lblackb" href="index.php?explore=userview&userv=$1">$1</a> wrote :<br />$2');
    array_push($format_replace, '</div>');
}

$str=preg_replace($format_search, $format_replace, $str);

它仅在出现次数正确时才会替换。所以它应该(对吗?)防止 html 被破坏或其他恶意攻击。你怎么看?

4

3 回答 3

4

PHP 中的 PCRE 和正则表达式确实允许递归http://php.net/manual/en/regexp.reference.recursive.php - 你需要它的(?R)语法。

但它通常只递归匹配,它不会递归应用您的替换字符串。preg_replace_callback因此,您至少需要使用。

很难开始工作,但我相信(完全未经测试)这可能适用于您的情况:

= preg_replace_callback('#\[quote=(.*?)\]((?:(?R)|.*?)+)\[/quote\]#is',
          'cb_bbcode_quote', $str);

现在回调返回包装的内容,之后它必须再次在 $match[1] 内部文本上调用相同的正则表达式,并且 preg_replace_callback-call 本身。

于 2011-05-08T15:33:26.187 回答
1

您可以简单地用开始的 div 标签替换开始的引号标签,结束部分也一样。如果用户弄乱了它的报价标签匹配,这只会变坏。或者,您可以使用内部部分递归引用函数:

<?php
function quote($str)
{
    if( preg_match('#\[quote=.*?\](.*)\[/quote\]#i', $str) )
         return quote(preg_replace('#\[quote=.*?\](.*)\[/quote\]#i', '$1', $str);
    return preg_replace('#\[quote=.*?\](.*)\[/quote\]#', '<div blabla>$1</div>', $str);
}
?>
于 2011-05-08T15:37:28.510 回答
0

像这样的递归语法正是正则表达式开始变得太弱的时候。您应该考虑使用某种解析器。

正则表达式(至少没有一些扩展),只能接受正则语言。为了具有递归语法,您需要一种上下文无关语言。这些需要更复杂的解析器。

于 2011-05-08T15:24:04.610 回答