替换 HTML 代码中的 BBCodes,反之亦然
Replace BBCodes in HTML codes and vice versa
我有一个带有 BBCodes 的句子,我想用 HTML 代码替换它:
$sentence = '[html style="font-size: 18px;" dir="ltr"][div style="font-size: 18px;" dir="ltr"][p style="font-weight: bold;"]Hello,[/p][p]You have got a new message from [a href="https://www.example.com/"]Example.com[/a][br][br].You could check your message on [a href="https://www.example.com/en/manager/inbox.html"]Manager[/a][/p][p][img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px"][div style="color: #D4192D; font-weight: bold;"]Example.com Team[/div][/p][/div][/html]';
$htmlTags = '<></>';
$bbTags = '/\[(.*)\](.*)\[\/(.*)\]/';
$new = preg_replace($bbTags, $htmlTags, $sentence);
echo $new;
输出为:
<html style="font-size: 18px;" dir="ltr"][div style="font-size: 18px;" dir="ltr"][p style="font-weight: bold;"]Hello,[/p][p]You have got a new message from [a href="https://www.example.com/"]Example.com[/a][br][br].You could check your message on [a href="https://www.example.com/en/manager/inbox.html"]Manager[/a][/p][p][img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px"][div style="color: #D4192D; font-weight: bold;"]Example.com Team[/div][/p][/div></html>
所以它没有涵盖整个句子。
我不想放置一组代码及其替换
PS: 句子可以根据具体情况更改
您可以使用以下 PHP code:
<?php
$sentence = '[html style="font-size: 18px;" dir="ltr"][div style="font-size: 18px;" dir="ltr"][p style="font-weight: bold;"]Hello,[/p][p]You have got a new message from [a href="https://www.example.com/"]Example.com[/a][br][br].You could check your message on [a href="https://www.example.com/en/manager/inbox.html"]Manager[/a][/p][p][img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px"][div style="color: #D4192D; font-weight: bold;"]Example.com Team[/div][/p][/div][/html]';
$rx = '~\[((\w+)\b[^]]*)\]((?>(?!\[\b).|(?R))*)\[\/]~s';
$tmp = '';
while (preg_match($rx, $sentence) && $tmp != $sentence) {
$tmp = $sentence;
$sentence = preg_replace($rx, '<></>', $sentence);
}
$sentence = preg_replace('~\[([^]]*)]~', '< />', $sentence);
echo $sentence;
输出:
<html style="font-size: 18px;" dir="ltr">
<div style="font-size: 18px;" dir="ltr">
<p style="font-weight: bold;">Hello,</p>
<p>You have got a new message from <a href="https://www.example.com/">Example.com</a><br /><br />.You could check your message on <a href="https://www.example.com/en/manager/inbox.html">Manager</a></p>
<p><img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px" />
<div style="color: #D4192D; font-weight: bold;">Example.com Team</div>
</p>
</div>
</html>
参见regex demo #1 and regex demo #2。
详情:
\[
- 一个 [
字符
((\w+)\b[^]]*)
- 第 1 组 (</code>):一个或多个单词字符(捕获到第 2 组),然后是单词边界和 <code>]
字符以外的零个或多个字符
]
- 一个 ]
字符
((?>(?!\[\b).|(?R))*)
- 第 3 组 (</code>):任何不是 <code>[
+ 第 2 组(作为一个整体)字符序列起点的字符,或者整个模式递归
\[\/]
- [/
字符串,第 2 组值,]
字符。
这是处理配对标签的模式。第二种模式处理非配对标签:
\[
- 一个 [
字符
([^]]*)
- 第 1 组 (</code>):除 <code>]
之外的任何零个或多个字符
]
- 一个 ]
字符。
显然,一次完成是不可能的,因为你必须处理嵌套标签,而且一个模式不能多次匹配相同的子字符串。
一个解决方案是从最里面的标签开始替换(里面没有其他括号标签的标签)。为此,您不需要递归模式,只需在描述文本内容时禁止使用左括号即可。
$sentence = '[html style="font-size: 18px;" dir="ltr"][div style="font-size: 18px;" dir="ltr"][p style="font-weight: bold;"]Hello,[/p][p]You have got a new message from [a href="https://www.example.com/"]Example.com[/a][br][br].You could check your message on [a href="https://www.example.com/en/manager/inbox.html"]Manager[/a][/p][p][img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px"][div style="color: #D4192D; font-weight: bold;"]Example.com Team[/div][/p][/div][/html]';
// proceed to the replacement of all self-closing tags first
$result = preg_replace('~\[ (br|hr|img)\b ([^]]*) ]~xi', '</>', $sentence);
// then replace the innermost tags until there's nothing to replace
$count = 0;
do {
$result = preg_replace('~
\[ ( (\w+) [^]]* ) ] # opening tag
( [^[]*+ ) # content without other bracketed tags
\[/ ] # closing tag
~xi', '<></>', $result, -1, $count);
} while ($count);
echo $result;
preg_replace
的第5个参数是一个变量引用,其中存储了替换的次数(这里是$count
)。此变量用作停止 do...while
循环的条件。 (当$count==0
没有更多的东西可以替换时)。
我有一个带有 BBCodes 的句子,我想用 HTML 代码替换它:
$sentence = '[html style="font-size: 18px;" dir="ltr"][div style="font-size: 18px;" dir="ltr"][p style="font-weight: bold;"]Hello,[/p][p]You have got a new message from [a href="https://www.example.com/"]Example.com[/a][br][br].You could check your message on [a href="https://www.example.com/en/manager/inbox.html"]Manager[/a][/p][p][img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px"][div style="color: #D4192D; font-weight: bold;"]Example.com Team[/div][/p][/div][/html]';
$htmlTags = '<></>';
$bbTags = '/\[(.*)\](.*)\[\/(.*)\]/';
$new = preg_replace($bbTags, $htmlTags, $sentence);
echo $new;
输出为:
<html style="font-size: 18px;" dir="ltr"][div style="font-size: 18px;" dir="ltr"][p style="font-weight: bold;"]Hello,[/p][p]You have got a new message from [a href="https://www.example.com/"]Example.com[/a][br][br].You could check your message on [a href="https://www.example.com/en/manager/inbox.html"]Manager[/a][/p][p][img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px"][div style="color: #D4192D; font-weight: bold;"]Example.com Team[/div][/p][/div></html>
所以它没有涵盖整个句子。
我不想放置一组代码及其替换
PS: 句子可以根据具体情况更改
您可以使用以下 PHP code:
<?php
$sentence = '[html style="font-size: 18px;" dir="ltr"][div style="font-size: 18px;" dir="ltr"][p style="font-weight: bold;"]Hello,[/p][p]You have got a new message from [a href="https://www.example.com/"]Example.com[/a][br][br].You could check your message on [a href="https://www.example.com/en/manager/inbox.html"]Manager[/a][/p][p][img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px"][div style="color: #D4192D; font-weight: bold;"]Example.com Team[/div][/p][/div][/html]';
$rx = '~\[((\w+)\b[^]]*)\]((?>(?!\[\b).|(?R))*)\[\/]~s';
$tmp = '';
while (preg_match($rx, $sentence) && $tmp != $sentence) {
$tmp = $sentence;
$sentence = preg_replace($rx, '<></>', $sentence);
}
$sentence = preg_replace('~\[([^]]*)]~', '< />', $sentence);
echo $sentence;
输出:
<html style="font-size: 18px;" dir="ltr">
<div style="font-size: 18px;" dir="ltr">
<p style="font-weight: bold;">Hello,</p>
<p>You have got a new message from <a href="https://www.example.com/">Example.com</a><br /><br />.You could check your message on <a href="https://www.example.com/en/manager/inbox.html">Manager</a></p>
<p><img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px" />
<div style="color: #D4192D; font-weight: bold;">Example.com Team</div>
</p>
</div>
</html>
参见regex demo #1 and regex demo #2。
详情:
\[
- 一个[
字符((\w+)\b[^]]*)
- 第 1 组 (</code>):一个或多个单词字符(捕获到第 2 组),然后是单词边界和 <code>]
字符以外的零个或多个字符]
- 一个]
字符((?>(?!\[\b).|(?R))*)
- 第 3 组 (</code>):任何不是 <code>[
+ 第 2 组(作为一个整体)字符序列起点的字符,或者整个模式递归\[\/]
-[/
字符串,第 2 组值,]
字符。
这是处理配对标签的模式。第二种模式处理非配对标签:
\[
- 一个[
字符([^]]*)
- 第 1 组 (</code>):除 <code>]
之外的任何零个或多个字符
]
- 一个]
字符。
显然,一次完成是不可能的,因为你必须处理嵌套标签,而且一个模式不能多次匹配相同的子字符串。
一个解决方案是从最里面的标签开始替换(里面没有其他括号标签的标签)。为此,您不需要递归模式,只需在描述文本内容时禁止使用左括号即可。
$sentence = '[html style="font-size: 18px;" dir="ltr"][div style="font-size: 18px;" dir="ltr"][p style="font-weight: bold;"]Hello,[/p][p]You have got a new message from [a href="https://www.example.com/"]Example.com[/a][br][br].You could check your message on [a href="https://www.example.com/en/manager/inbox.html"]Manager[/a][/p][p][img src="https://www.example.com/assets/images/logo-default-120x50.png" width="120px" height="80px"][div style="color: #D4192D; font-weight: bold;"]Example.com Team[/div][/p][/div][/html]';
// proceed to the replacement of all self-closing tags first
$result = preg_replace('~\[ (br|hr|img)\b ([^]]*) ]~xi', '</>', $sentence);
// then replace the innermost tags until there's nothing to replace
$count = 0;
do {
$result = preg_replace('~
\[ ( (\w+) [^]]* ) ] # opening tag
( [^[]*+ ) # content without other bracketed tags
\[/ ] # closing tag
~xi', '<></>', $result, -1, $count);
} while ($count);
echo $result;
preg_replace
的第5个参数是一个变量引用,其中存储了替换的次数(这里是$count
)。此变量用作停止 do...while
循环的条件。 (当$count==0
没有更多的东西可以替换时)。