我正在开发一个论坛系统,该系统可解析[b]some bold text[/b]
之类的BBCode,并在通过PHP输出时对其应用HTML格式。我所有的表达式都起作用,但是我在弄清楚如何处理特定情况(特别是关于嵌套引用块)时遇到了麻烦。
在论坛上,您可能有一个用户引用另一个用户。我已经成功地使用以下格式进行了格式化:
#\[quote="(.*?);(\w*?)"\]\s*(.*?)\s*\[\/quote\]#
并调用preg_replace()
将其替换为:
<blockquote id="quote-$2"><p>$3<br> - $1</p></blockquote>
这是working example。
举一个真实的例子,您可能在论坛上看到一个用户Stan
想要引用John
,并将其添加到文本区域以供提交:
[quote="John;2"]John's sentence[/quote]
____________
Stan's reply
但是,如果约翰在自己的帖子中引用了玛丽,会发生什么?
[quote="John;2"][quote="Mary;1"]Mary's sentence[/quote]John's sentence[/quote]
____________
Stan's reply
我的正则表达式将捕获除最后一个[/quote]
之外的所有字符,但是即使我能够捕获整个字符串,我也不确定如何格式化它。理想情况下,我希望输出看起来像这样:
"Mary's sentence"
- Mary
"John's sentence"
- John
__________________________
Stan's reply
在HTML中:
<blockquote id="quote-2">
<blockquote id="quote-1"><p>"Mary's sentence"<br> - Mary</p></blockquote>
<p>"John's sentence"<br> - John</p>
</blockquote>
<p>Stan's reply</p>
我可以使用正则表达式捕获和格式化重复的嵌套标签吗?如果有100个嵌套的报价块怎么办?显然,我可以写一个荒谬而冗长的重复表达式(肯定会有局限性),但是必须有一种更好的方法来解决这个问题。我应该使用另一种方法吗?
对于similar question already exists,我感到很抱歉,但是我在SO上浏览了许多问题,但仍不确定应该采用哪种方法。
答案 0 :(得分:1)
这个想法是确保您只匹配最里面的BB标签。匹配[quote
和[/quote]
之间不包含其他[quote=
的所有文本,并进行替换,直到没有找到这样的匹配为止。它也基于您的实际标签内容中没有[quote=
的假设,但是在大多数情况下是正确的。另一个假设是属性用"
引起来,并且里面不能有其他双引号。
因此,您可以使用
$s = '[quote="John;2"][quote="Mary;1"]Mary\'s sentence[/quote]John\'s sentence[/quote]';
$repl = '<blockquote id="quote-$2"><p>$3 <br> - $1</p></blockquote>';
$reg = '~\[quote="([^"]*);(\w*)"]\s*((?:(?!\[quote=).)*?)\s*\[/quote]~si';
while (preg_match($reg, $s)) {
$s = preg_replace($reg, $repl, $s);
}
echo $s;
// => <blockquote id="quote-2"><p><blockquote id="quote-1"><p>Mary's sentence <br> - Mary</p></blockquote>John's sentence <br> - John</p></blockquote>
请参见PHP demo。正则表达式是
'~\[quote="([^"]*);(\w*)"]\s*((?:(?!\[quote=).)*?)\s*\[/quote]~si'
请参见regex demo。
详细信息
\[quote="
-文字子字符串([^"]*)
-捕获第1组:"
以外的任意0+个字符;
-冒号(\w*)
-捕获第2组:0个以上的字符字符"]
-文字子字符串\s*
-超过0个空格((?:(?!\[quote=).)*?)
-捕获第3组:尽可能少的任何字符,而不以[quote=
文本开头\s*
-超过0个空格\[/quote]
-文字[/quote]
子字符串。漂亮打印是一项额外的任务,其中有a couple of solutions mentioned here。