preg_replace : 从 BBCode 获取另一个 html 标签内的 html 标签

preg_replace : getting a html tag inside an other html tag from BBCode

所以我正在尝试制作一个 php 函数来从 BBCode-style 表单中获取 HTML 标签。事实上,我可以使用 preg_replace 轻松获得标签。但是当我在同一个 bbcode 中有一个 bbcode 时,我遇到了一些麻烦...

像这样:

[blue]My [black]house is [blue]very[/blue] beautiful[/black] today[/blue]

所以,当我 "parse" 它时,我总是保留蓝色的 bbcode。像 :

My house is [blue]very[/blue] beautiful today

除了第一个蓝色标签内的黑色标签内的蓝色标签外,所有内容都是彩色的。

我该怎么做?

有了更多信息,我试过了:

Regex: "/\[blue\](.*)\[\/blue\]/si" or "/\[blue\](.*)\[\/blue\]/i"
Getting : "My house is [blue]very[/blue] beautiful today"

Regex : "/\[blue\](.*?)\[\/blue\]/si" or "/\[blue\](.*)\[\/blue\]/Ui"
Getting : "My house is [blue]very beautiful today[/blue]"

我必须循环 preg_replace 吗? regex-style 没有循环的方法吗?

感谢您的关心。 :)

不应该在产品上重新发明轮子,而是选择 well-tested 插件是正确的。但是,如果您正在试验或从事宠物项目,请务必继续试验,享受乐趣并在过程中获得重要知识。

话虽如此,您可以尝试使用正则表达式。我会在下面为你分解。

(\[(.*?)\])(.*?)(\[/\])

哲学

在像这样解析标记时,您实际寻求的是 将标签与其成对 .

进行匹配

因此,您可以采取的一种干净的方法是 运行 一个循环,并且 每次都捕获最外层的标签对 并替换它。

因此,在上面给定的正则表达式中,捕获组 将为您提供以下信息;

  1. 开始标记(完整)[black]
  2. 开始标签(标签名称)black
  3. 开始和结束标签之间的内容My [black]house is [blue]very[/blue] beautiful[/black] today
  4. 结束标记 [/blue]

所以,你可以用$2来判断你正在处理的tag,替换成

<tag></tag>
// or even
<></>

哪个会给你;

// in first iteration
<tag>My [black]house is [blue]very[/blue] beautiful[/black] today</tag>

// in second iteration
<tag>My <tag2>house is [blue]very[/blue] beautiful</tag2> today</tag>

// in third iteration
<tag>My <tag2>house is <tag3>very</tag3> beautiful</tag2> today</tag>

代码

$text = "[blue]My [black]house is [blue]very[/blue] beautiful[/black] today[/blue]";

function convert($input)
{
    $control = $input;

    while (true) {
        $input = preg_replace('~(\[(.*?)\])(.*)(\[/\])~s', '<></>', $input);

        if ($control == $input) {
            break;
        }

        $control = $input;
    }

    return $input;
}


echo convert($text);

正如其他人所说,不要试图重新发明轮子。
但是,您可以使用 递归 方法:

<?php

$text = "[blue]My [black]house is [blue]very[/blue] beautiful[/black] today[/blue]";

$regex = '~(\[ ( (?>[^\[\]]+) | (?R) )* \])~x';

$replacements = array(  "blue" => "<bleu>", 
                        "black" => "<noir>", 
                        "/blue" => "</bleu>",
                        "/black" => "</noir>");

$text = preg_replace_callback($regex,
    function($match) use ($replacements) {
        return $replacements[$match[2]];
    },
    $text);

echo $text;
# <bleu>My <noir>house is <bleu>very</bleu> beautiful</noir> today</bleu>

?>

在这里,每个颜色标签都被其对应的法语(刚刚编造的)颜色标签所取代,请参阅有关该主题的 a demo on ideone.com. To learn more about recursive patterns, have a look at the PHP documentation