preg_replace_callback搞乱文本问题

时间:2016-12-16 21:55:34

标签: php preg-replace-callback

我正在尝试替换这样的bbcode引号:

[quote=username]text[/quote] 

工作正常。

如果有人在引用某人,而且还在引用其他人,则会出现问题,即它似乎只会替换其中一个,例如此类文字:

[quote=person1][quote=person2][quote]test quoted text[/quote]

another quote[/quote]
one more quote[/quote]

以下是我的功能:

// replace specific-user quotes, called by quotes()
function replace_quotes($matches)
{
    global $db;

    $find_quoted = $db->sqlquery("SELECT `username`, `user_id` FROM `users` WHERE `username` = ?", array($matches[1]));
    if ($db->num_rows() == 1)
    {
        $get_quoted = $find_quoted->fetch();
        if (core::config('pretty_urls') == 1)
        {
            $profile_link = '/profiles/' . $get_quoted['user_id'];
        }
        else
        {
            $profile_link = '/index.php?module=profile&user_id=' . $get_quoted['user_id'];
        }
        return '<blockquote><cite><a href="'.$profile_link.'">'.$matches[1].'</a></cite>'.$matches[2].'</blockquote>';
    }
    else
    {
        return '<blockquote><cite>'.$matches[1].'</cite>'.$matches[2].'</blockquote>';
    }
}

// find all quotes
function quotes($body)
{
    // Quoting an actual person, book or whatever
    $pattern = '/\[quote\=(.+?)\](.+?)\[\/quote\]/is';

    $body = preg_replace_callback($pattern, 'replace_quotes', $body);

    // Quote on its own
    $pattern = '/\[quote\](.+?)\[\/quote\]/is';
    $replace = "<blockquote><cite>Quote</cite>$1</blockquote>";

    while(preg_match($pattern, $body))
    {
        $body = preg_replace($pattern, $replace, $body);
    }

    return $body;
}

$ body =从某个地方发送给它的实际文本,例如对某事的评论

嵌套的东西也有用,我错过了什么?因为它应该取代每个单独的报价。

1 个答案:

答案 0 :(得分:1)

想法是重写你的功能(未经测试):

function quotes($body)
{
    $pattern = '~\[quote=([^]]+)]([^[]*+(?:\[(?!/?quote\b)[^[]*)*+)\[/quote]~i';
    do {
        $body = preg_replace_callback($pattern, 'replace_quotes', $body, -1, $count);
    } while ($count);

    return $body;
}

([^[]*(?:\[(?!/?quote\b)[^[]*)*)只匹配子字符串而不打开或关闭引号标记。这样你就可以确保只得到最里面的引号。

请注意,PHP手册中还有另一种解析递归结构的方法,但我不确定它是否非常有效。 (请参阅preg_replace_callback页面。)