在论坛中的递归引用

时间:2011-05-08 15:20:24

标签: php regex recursion forum quote

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

引用的消息标签看起来像[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破坏或其他恶意攻击。你觉得怎么样?

3 个答案:

答案 0 :(得分: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自身。

答案 1 :(得分: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);
}
?>

答案 2 :(得分:0)

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

正则表达式(至少没有一些扩展名)只能接受regular languages。为了获得递归语法,您需要context-free language。这些需要更复杂的解析器。