我想写一个symple(由一个preg_replace调用组成)论坛解析器,我遇到了嵌套标签的问题。
E.g。如果有人引用某人引用某人,我就无法达到正确的行为。
拥有:
[quote=Tom]
[quote=Jerry]
Lorem
[/quote]
Ipsum
[/quote]
Dolor.
我想要这样的事情:
<blockquote>
<p><strong>Tom wrote</strong></p>
<blockquote>
<p><strong>Jerry wrote:</strong></p>
<p>Lorem</p>
</blockquote>
Ipsum
</blockquote>
Dolor.
我有这段代码:
preg_replace('~\[quote (.+)\](.+)\[/quote\]~is', '<blockquote><p><strong>$1</strong> wrote:</p><p>$2</p></blockquote>', $value);
这个版本很贪心。如果我有两个单独的[quote]
块,则正则表达式将所有文本包装在第一个[quote]
和第二个[/quote]
之间。
如果我添加了U
修饰符,那就太不合适了 - 第一个[quote]
标记与第一个(嵌套且不相关)[/quote]
标记配对。
感谢您的帮助!
答案 0 :(得分:1)
有PEAR HTML_BBCodeParser包,PHP也有解析这样的代码的原生扩展,请查看以下示例:http://www.php.net/manual/en/function.bbcode-create.php
答案 1 :(得分:1)
不要使用正则表达式。使用提供的官方PECL扩展程序:
示例(取消了文档):
<?php
$arrayBBCode=array(
''=> array('type' => BBCODE_TYPE_ROOT, 'childs' => '!i'),
'i'=> array('type' => BBCODE_TYPE_NOARG, 'open_tag' => '<i>',
'close_tag' => '</i>', 'childs' => 'b'),
'url'=> array('type' => BBCODE_TYPE_OPTARG,
'open_tag' => '<a href="{PARAM}">', 'close_tag' => '</a>',
'default_arg' => '{CONTENT}',
'childs' => 'b,i'),
'img'=> array('type' => BBCODE_TYPE_NOARG,
'open_tag' => '<img src="', 'close_tag' => '" />',
'childs' => ''),
'b'=> array('type'=>BBCODE_TYPE_NOARG, 'open_tag' => '<b>',
'close_tag' => '</b>'),
);
$text = <<<EOF
[b]Bold Text[/b]
[i]Italic Text[/i]
[url]http://www.php.net/[/url]
[url=http://pecl.php.net/][b]Content Text[/b][/url]
[img]http://static.php.net/www.php.net/images/php.gif[/img]
[url=http://www.php.net/]
[img]http://static.php.net/www.php.net/images/php.gif[/img]
[/url]
EOF;
$BBHandler = bbcode_create($arrayBBCode);
echo bbcode_parse($BBHandler, $text);
?>
答案 2 :(得分:0)
在递归正则表达式的帮助下:
function replace_quotes_callback($matches) {
$cite = empty($matches[1]) ? '' : '<p><strong>' . $matches[1] . '</strong> wrote:</p>';
return '<blockquote>' . $cite . '<p>' . replace_quotes($matches[2]) . '</p></blockquote>';
}
function replace_quotes($data) {
return preg_replace_callback('~\[quote(?:=([^\]]+))?\]((?:(?R)|.)*?)\[/quote\]~s', 'replace_quotes_callback', $data);
}
模式仅匹配最外面的引用块,回调函数replace_quotes_callback
通过递归调用replace_quotes
替换自身内部的引号。