我正在开发一个论坛系统,该系统解析类似[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>
这是一个工作示例。
对于您可能在论坛上看到的一个真实示例,用户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>
我可以使用regex捕获和格式化重复的嵌套标签吗?如果有100个嵌套的引号块怎么办?显然,我可以写一个长得离谱、重复的表达(当然会有局限性(,但必须有更好的方法来解决这个问题。还有其他方法我应该用吗?
如果已经存在类似的问题,我很抱歉,但我已经看了很多关于SO的问题,仍然不确定我应该采取哪种方法。
这样做的目的是确保只匹配最里面的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演示。正则表达式是
'~[quote="([^"]*);(w*)"]s*((?:(?![quote=).)*?)s*[/quote]~si'
请参阅regex演示。
详细信息
[quote="
-文字子字符串([^"]*)
-捕获组1:除"
之外的任何0+个字符;
-冒号(w*)
-捕获组2:0+字字符"]
-文字子字符串s*
-0+空白((?:(?![quote=).)*?)
-捕获组3:任何字符,尽可能少,不启动[quote=
文本s*
-0+空白[/quote]
-一个字面[/quote]
子字符串
漂亮的打印是一项额外的任务,这里提到了几个解决方案。