替换 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;

demo

preg_replace的第5个参数是一个变量引用,其中存储了替换的次数(这里是$count)。此变量用作停止 do...while 循环的条件。 (当$count==0没有更多的东西可以替换时)。