如何捕获和格式化输出嵌套格式标签?
How can I capture and format on output nested format tags?
我正在开发一个论坛系统,它像 [b]some bold text[/b]
一样解析 BBCode,并在通过 PHP 输出时应用 HTML 格式。我的所有表达式都有效,但我无法弄清楚如何处理特定情况,特别是关于嵌套引号块。
在论坛上,您可能让一个用户引用另一个用户的话。我已经成功地使用以下格式对其进行了格式化:
#\[quote="(.*?);(\w*?)"\]\s*(.*?)\s*\[\/quote\]#
并调用 preg_replace()
将其替换为:
<blockquote id="quote-"><p><br> - </p></blockquote>
这里有个working example.
对于您可能在论坛上看到的真实示例,用户 Stan
想要引用 John
,将其添加到文本区域以供提交:
[quote="John;2"]John's sentence[/quote]
____________
Stan's reply
但是如果约翰在他的 post 中引用了玛丽的话会怎样?
[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 的问题,但仍然不确定我应该采用哪种方法。
我们的想法是确保您只匹配最里面的 BB 标签。匹配 [quote
和 [/quote]
之间不包含另一个 [quote=
的所有文本,并替换直到找不到这样的匹配项。它也基于您的实际标签内容中没有 [quote=
的假设,但在大多数情况下它是正确的。另一个假设是属性是 "
-quoted 并且里面不能有其他双引号。
所以,您可以使用
$s = '[quote="John;2"][quote="Mary;1"]Mary\'s sentence[/quote]John\'s sentence[/quote]';
$repl = '<blockquote id="quote-"><p> <br> - </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=
text
\s*
- 0+ 个空格
\[/quote]
- 文字 [/quote]
子字符串。
漂亮打印是一项额外的任务,还有a couple of solutions mentioned here。
我正在开发一个论坛系统,它像 [b]some bold text[/b]
一样解析 BBCode,并在通过 PHP 输出时应用 HTML 格式。我的所有表达式都有效,但我无法弄清楚如何处理特定情况,特别是关于嵌套引号块。
在论坛上,您可能让一个用户引用另一个用户的话。我已经成功地使用以下格式对其进行了格式化:
#\[quote="(.*?);(\w*?)"\]\s*(.*?)\s*\[\/quote\]#
并调用 preg_replace()
将其替换为:
<blockquote id="quote-"><p><br> - </p></blockquote>
这里有个working example.
对于您可能在论坛上看到的真实示例,用户 Stan
想要引用 John
,将其添加到文本区域以供提交:
[quote="John;2"]John's sentence[/quote]
____________
Stan's reply
但是如果约翰在他的 post 中引用了玛丽的话会怎样?
[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 的问题,但仍然不确定我应该采用哪种方法。
我们的想法是确保您只匹配最里面的 BB 标签。匹配 [quote
和 [/quote]
之间不包含另一个 [quote=
的所有文本,并替换直到找不到这样的匹配项。它也基于您的实际标签内容中没有 [quote=
的假设,但在大多数情况下它是正确的。另一个假设是属性是 "
-quoted 并且里面不能有其他双引号。
所以,您可以使用
$s = '[quote="John;2"][quote="Mary;1"]Mary\'s sentence[/quote]John\'s sentence[/quote]';
$repl = '<blockquote id="quote-"><p> <br> - </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=
text\s*
- 0+ 个空格\[/quote]
- 文字[/quote]
子字符串。
漂亮打印是一项额外的任务,还有a couple of solutions mentioned here。