多维BBCODE
Multidimentional BBCODE
我正在努力使自己成为 PHP 中的 BBCODE 解析器。
现在我有以下正则表达式:
\[quote\](.*?)\[\/quote\]
这应该替换为:
<div class='quote'><div class='quotetext'></div></div>
这一切都很完美,直到我有一个“多维”post示例:
[quote] [quote] [quote] text [/quote] [/quote] [/quote]
这应该有以下结果:
<div class='quote'><div class='quotetext'>
<div class='quote'><div class='quotetext'>
<div class='quote'><div class='quotetext'>
text
</div></div>
</div></div>
</div></div>
现在得到以下结果:
<div class='quote'><div class='quotetext'> [quote] [quote] text </div></div> [/quote] [/quote]
Php:
preg_replace("/\[quote\](.*?)\[\/quote\]/", "<div class='quote'><div class='quotetext'></div></div>", $text);
我希望有人能帮我解决这个问题。谢谢
一次通过正则表达式方法:
- 构造一个数组,将 bbcode 标签与相应的 html 代码相关联。
- 编写一个能够匹配嵌套(或不匹配)引用 bbcode 标签的模式。利息将是双倍的,因为它只允许提取有效部分(平衡的),然后进行替换。
- 使用关联数组在回调函数中使用
strtr
进行简单替换。
Pro:这是相对较快的,因为它只需要一次传递并且因为使用了 strtr
.
缺点:它不灵活,因为它只考虑 [quote]
而不是 [quote param="bidule"]
或 [QUOTE]
之类的标签。 (然而,没有什么可以禁止编写更详细的回调函数并稍微更改模式)。
$corr = [
'[quote]' => '<div class="quote"><div class="quotetext">',
'[/quote]' => '</div></div>'
];
$pat = '~ \[quote]
# all that is not a quote tag
(?<content> [^[]*+ (?: \[ (?! /?quote] ) [^[]* )*+ )
# an eventual recursion ( (?R) is a reference to the whole pattern)
(?: (?R) (?&content) )*+
\[/quote]
~x';
$result = preg_replace_callback($pat, fn($m) => strtr($m[0], $corr), $str);
多遍的更经典的方法:
- 构建一个禁止嵌套引号标签的模式,这样只会替换内部标签。
- 将替换放在一个 while 循环中,并在没有更多要替换的标签时停止它(使用
preg_replace
计数参数了解这一点)
$pat = '~ \[quote] ( [^[]*+ (?: \[ (?! /? quote] ) [^[]* )*+ ) \[/quote] ~x';
$repl = '<div class="quote"><div class="quotetext"></div></div>';
$result = $str;
$count = 0;
do {
$result = preg_replace($pat, $repl, $result, -1, $count);
} while($count);
pro:比第一种方法更灵活,因为您可以轻松更改模式和替换字符串。
缺点:明显较慢,因为您需要 n+1 循环,其中 n 是最大嵌套级别。
顺便说一句:当您只需要一个 html 标签并且 blockquote
标签存在时,您出于什么原因想要用两个 div 替换一个糟糕的 [quote]
标签!
我正在努力使自己成为 PHP 中的 BBCODE 解析器。
现在我有以下正则表达式:
\[quote\](.*?)\[\/quote\]
这应该替换为:
<div class='quote'><div class='quotetext'></div></div>
这一切都很完美,直到我有一个“多维”post示例:
[quote] [quote] [quote] text [/quote] [/quote] [/quote]
这应该有以下结果:
<div class='quote'><div class='quotetext'>
<div class='quote'><div class='quotetext'>
<div class='quote'><div class='quotetext'>
text
</div></div>
</div></div>
</div></div>
现在得到以下结果:
<div class='quote'><div class='quotetext'> [quote] [quote] text </div></div> [/quote] [/quote]
Php:
preg_replace("/\[quote\](.*?)\[\/quote\]/", "<div class='quote'><div class='quotetext'></div></div>", $text);
我希望有人能帮我解决这个问题。谢谢
一次通过正则表达式方法:
- 构造一个数组,将 bbcode 标签与相应的 html 代码相关联。
- 编写一个能够匹配嵌套(或不匹配)引用 bbcode 标签的模式。利息将是双倍的,因为它只允许提取有效部分(平衡的),然后进行替换。
- 使用关联数组在回调函数中使用
strtr
进行简单替换。
Pro:这是相对较快的,因为它只需要一次传递并且因为使用了 strtr
.
缺点:它不灵活,因为它只考虑 [quote]
而不是 [quote param="bidule"]
或 [QUOTE]
之类的标签。 (然而,没有什么可以禁止编写更详细的回调函数并稍微更改模式)。
$corr = [
'[quote]' => '<div class="quote"><div class="quotetext">',
'[/quote]' => '</div></div>'
];
$pat = '~ \[quote]
# all that is not a quote tag
(?<content> [^[]*+ (?: \[ (?! /?quote] ) [^[]* )*+ )
# an eventual recursion ( (?R) is a reference to the whole pattern)
(?: (?R) (?&content) )*+
\[/quote]
~x';
$result = preg_replace_callback($pat, fn($m) => strtr($m[0], $corr), $str);
多遍的更经典的方法:
- 构建一个禁止嵌套引号标签的模式,这样只会替换内部标签。
- 将替换放在一个 while 循环中,并在没有更多要替换的标签时停止它(使用
preg_replace
计数参数了解这一点)
$pat = '~ \[quote] ( [^[]*+ (?: \[ (?! /? quote] ) [^[]* )*+ ) \[/quote] ~x';
$repl = '<div class="quote"><div class="quotetext"></div></div>';
$result = $str;
$count = 0;
do {
$result = preg_replace($pat, $repl, $result, -1, $count);
} while($count);
pro:比第一种方法更灵活,因为您可以轻松更改模式和替换字符串。
缺点:明显较慢,因为您需要 n+1 循环,其中 n 是最大嵌套级别。
顺便说一句:当您只需要一个 html 标签并且 blockquote
标签存在时,您出于什么原因想要用两个 div 替换一个糟糕的 [quote]
标签!