我正在尝试替换这样的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 =从某个地方发送给它的实际文本,例如对某事的评论
嵌套的东西也有用,我错过了什么?因为它应该取代每个单独的报价。
答案 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
页面。)