PHP BBCode正则表达式替换


PHP BBCode regex replacement

如何替换:

<tag attr="z">
    <tag attr="y">
        <tag attr="x"></tag>
    </tag>
</tag>

至:

<tag attr="z">
    [tag=y]
        <tag attr="x"></tag>
    [/tag]
</tag>

不使用扩展?

我尝试失败:

preg_replace("#<tag attr='"y'">(.+?)</tag>#i", "[tag=y]''1[/tag]", $text);

PHP的regex实现支持PCRE的递归模式。然而,我会犹豫是否使用这样的功能,因为它具有神秘的性质。然而,既然你问:

不使用扩展?

在这里:

<?php
$html = '<tag attr="z">
    <tag attr="y">
        <tag>
            <tag attr="more" stuff="here">
                <tag attr="x"></tag>
            </tag>
        </tag>
    </tag>
</tag>
';
$attr_regex = "(?:'s+'w+'s*='s*(?:'[^']*'|'"[^'"]*'"))";
$recursive_regex = "@
    <tag's+attr='"y'">         # match opening tag with attribute 'y'
    (                          # start match group 1
      's*                      #   match zero or more white-space chars
      <('w+)$attr_regex*''s*>  #   match an opening tag and store the name in group 2
      (                        #   start match group 3
        [^<]+                  #     match one or more chars other than '<'
        |                      #     OR
        (?1)                   #     match whatever the pattern from match group 1 matches (recursive call!)
      )*                       #   end match group 3
      </''2>                   #   match the closing tag with the same name stored in group 2
      's*                      #   match zero or more white-space chars
    )                          # end match group 1
    </tag>                     # match closing tag
    @x";
echo preg_replace($recursive_regex, "[tag=y]$1[/tag]", $html);
?>

它将打印以下内容:

<tag attr="z">
    [tag=y]
        <tag>
            <tag attr="more" stuff="here">
                <tag attr="x"></tag>
            </tag>
        </tag>
    [/tag]
</tag>