Замена регулярного выражения PHP BBCode

Как я могу заменить:

<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)


Что ж, реализация регулярных выражений 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
Почему я не могу запустить этот код регулярного выражения дважды? - person Bestudio; 04.09.2012
comment
@Bestudio, ты можешь. Может быть, создать еще один вопрос? - person Bart Kiers; 04.09.2012
comment
@Bestudio, извини, я не понимаю, что ты имеешь в виду. Я не знаю, что вы имели в виду, запустив его дважды, и я не знаю, что вы имеете в виду, имея пример. Как видно из моего ответа, регулярное выражение работает просто отлично, а мой фрагмент кода самодостаточен: вы можете запустить его и убедиться, что он работает. Если у вас есть другая проблема, я предлагаю вам создать для нее еще один вопрос (как я предлагал ранее). Удачи! - person Bart Kiers; 04.09.2012