PHP BBCode замяна на regex

Как мога да заменя:

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

to:

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

Без да използвате разширения?

Опитах безуспешно:

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

person Bestudio    schedule 03.09.2012    source източник
comment
preg_replace(#‹tag attr=\y\›(.+?)‹/tag›#i, [tag=y]\\1[/tag], $text);   -  person Bestudio    schedule 03.09.2012
comment
Щракнете върху редактиране, за да актуализирате въпроса си с повече информация, това е по-лесно за четене от коментарите.   -  person Jocelyn    schedule 03.09.2012


Отговори (1)


Е, изпълнението на regex на PHP поддържа рекурсивните модели на 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>
person Bart Kiers    schedule 03.09.2012
comment
Защо не мога да стартирам този Regex код два пъти? - person Bestudio; 04.09.2012
comment
@Bestudio, можеш. Може би да създадете друг въпрос? - person Bart Kiers; 04.09.2012
comment
@Bestudio, съжалявам, не знам какво имаш предвид. Не знам какво имате предвид, като го пуснете два пъти и не знам какво имате предвид, като имате пример. Както можете да видите от моя отговор, регулярният израз работи добре и моят кодов фрагмент е самостоятелен: можете да го стартирате и да видите, че работи. Ако имате друг проблем, предлагам ви да създадете друг въпрос за него (както предложих по-рано). Късмет! - person Bart Kiers; 04.09.2012