Php 论坛中的递归引用

Php 论坛中的递归引用,php,regex,recursion,forum,quote,Php,Regex,Recursion,Forum,Quote,我在一个用PHP编写的网站上为自己的个人论坛编写了一个报价函数 message quoted标记看起来像[quote=username]message[/quote],因此我编写了该函数: $str=preg_replace('#\[quote=(.*?)\](.*?)\[/quote\]#is', '<div class="messageQuoted"><i><a href="index.php?explore=userview&userv=$1">

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

message quoted标记看起来像
[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);
$str=preg#u replace('.\[quote=(.*?)\](.*?\[/quote\]]is','writed:$2',$str);
如果quote为1,则此方法有效,但如果用户引用quote,则此方法无效。所以我需要一种递归引用来应用这种行为

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

编辑

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

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);
if(preg#u match#u all('.\[quote=(.*?\])(.*?)#is',$str,$matches)==preg#u match#u all('.\[/quote\]#is',$str matches)){
数组推送($format\u search,'.\[quote=(.*?\])(.*is');
数组推送($format\u search,\\[/quote\]\\35; is');
数组推送($format\u replace,'writed:
$2'); 数组推送($format\u replace,''); } $str=preg\u replace($format\u search,$format\u replace,$str);

仅当发生次数正确时,才会回复。所以它应该(对吗?)防止html破坏或其他恶意攻击。你认为呢?

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


正则表达式(至少没有一些扩展)只能接受。为了拥有递归语法,您需要一个。这些需要更复杂的解析器。

PHP中的PCRE和正则表达式确实允许递归-您将需要
(?R)
语法

但它通常只递归地匹配,它不会递归地应用替换字符串。因此,您至少需要使用
preg\u replace\u callback

很难开始工作,但我相信(完全未经测试)在您的情况下可能会这样做:

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

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

您只需将开始引号标记替换为开始div标记,并将结束部分替换为结束部分。只有当用户弄乱了它的报价标签匹配时,这种情况才会变糟。 或者,您可以使用内部部分递归quote函数:

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

你不能用正则表达式进行递归(无限制嵌套)。@SLaks你可以在PHP中使用,它实际上工作得非常灵活。不过这通常还是个坏主意。@SLaks,不,那不是真的。除了PHP(正如Konrad已经提到的),Perl和.NET正则表达式实现还支持递归模式。我也同意康拉德的观点,即在生产代码中使用这些功能是一个坏主意,但仍然是可能的。因此,您认为Mel解决方案是错误的O@Slaks当前位置你又犯了“你不能在正则表达式中胡说八道”的愚蠢行为。你当然可以!例如,下面是如何匹配具有无限嵌套的paren:
\((?:[^()]*+\(?0))*\)
。小菜一碟。真的很圆滑。嗯……你的第一个简单解决方案听起来不错!“这只会变坏”是什么意思。regex也是一样:如果用户弄乱了bbcode,同样:regex不起作用。请尝试检查我在edit…@kwichz上的示例,递归实现仅替换正确配对的引号。如果有多个开头引号,而只有一个结尾引号,那么在不确保字符串是一对的情况下替换字符串会使布局变得混乱。也许最好的方法是计算开始和结束引号标记,如果它们不匹配,返回重新编辑,然后替换前面提到的开始和结束。是的,你是对的:)我尝试递归实现!这对你来说是真正的解决方案吗?因为使用regex和bbcode,每个人都说这只是一种变通方法,而不是解决方案!我真的不知道为什么:)如果我复制并粘贴递归实现,我会在用PHP解析时出错?!?!?添加了我自己的解决方案,因为您的递归模式不起作用!你觉得怎么样?安全吗?:)当今许多流行语言的大多数正则表达式实现都支持正则表达式模式中的反向引用,这使它们比常规语言更能接受。哈马尔:只要我们有了
(.*)\1
,我们就把你的形式语言理论抛到了九霄云外。那是什么时候,比如1970年?即使是POSIX正则表达式,陈旧而脆弱,也需要backref支持。现代正则表达式远远不止于此,包括PHP。现代正则表达式确实完全等同于递归下降解析器。@tchrist:那么它们就不再是真正的正则表达式了,是吗?它们更像是语法相似的解析器规范。我将保留完整的答案,尽管我意识到OP可能比形式语言理论更感兴趣的是一个实用的解决方案:)