我在一个用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破坏或其他恶意攻击。你觉得怎么样?
答案 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。这些需要更复杂的解析器。