регулярное выражение, php и вложенное зло (? R) - PullRequest
4 голосов
/ 13 января 2012

ОБНОВЛЕНИЕ

Так что я до сих пор возился с этим и дошел до поиска всех экземпляров тегов, хотя я бы предпочел ПРОСТО найти самый сложный экземпляр, какжизнь была бы проще таким образом ... В любом случае вот что я получил ..

/(({{)(?:(?=([^\/][^ ]*?))\3|(\/[\w])))([a-zA-Z0-9\$\'\"\s\#\%\^\&\!\.\_\+\=\-\\\*\(\)\ ]+?}})/

Есть ли ЛЮБЫЙ гуру регулярных выражений, который мог бы дать мне несколько указателей или регулярное выражение, имитирующее то, что мне нужно?Который получает только самый глубокий сложенный экземпляр {{tag}}, который заканчивается следующим образом {{// tag}}

ORIGINAL

Хорошо, так что у меня естьпроблема, которую я видел у других, но с другим подходом к ней .. Или так я думал .. Поэтому мне любопытно, может ли кто-нибудь еще помочь мне решить эту проблему дальше ..

У меня полная база данныхшаблонов, с которыми мне нужно работать в PHP, эти шаблоны создаются и используются другой системой, поэтому их нельзя изменить.При этом к этим шаблонам добавлены теги стиля иерархии.Что мне нужно сделать, это получить эти шаблоны из базы данных, а затем программно найти эти теги, их имя функции (или имя тега) и их внутреннее содержимое, а также все, что следует за именем функции (тега) в скобках.Пример одного из этих тегов: {{FunctionName some (otherStuff)! Here}} Некоторый контент находится внутри, и он заканчивается {{/ FunctionName}}

Это - то, где это становится более забавным, шаблоныесть другой случайный тег, который, как я предполагаю, является «переменным» стилем этих тегов, так как они всегда имеют одинаковый синтаксис.Это выглядит примерно так: $ {RandomTag}, но бывают случаи, когда есть стиль функции 1, но без конечного тега, например .. {{RandomLoner}}

Пример шаблона ...

{{FunctionTag (Condition?)}}
    <div>This is an {{CheckOfSomeSort someTimesThese !orThese}}
        example of some {{Random}} data
    {{/CheckOfSomeSort}} that will be ${worked} on</div>
{{/FunctionTag}}

Хорошо, это ни в коем случае не реальный шаблон, но он следует всем правилам, которые я видел до сих пор.

Теперь я пробовал разные вещи с regex и preg_match_all, чтобы вытащитьспички, и получить каждый из них в хороший массив.До сих пор я получил следующее (использовал его на примере шаблона, чтобы убедиться, что он работает до сих пор)

Array
(
    [0] => Array
        (
            [0] => {{CheckOfSomeSort someTimesThese !orThese}}example of some datas{{/CheckOfSomeSort}}
            [1] => {{CheckOfSomeSort someTimesThese !orThese}}
            [2] => CheckOfSomeSort
            [3] => example of some data
            [4] => {{/CheckOfSomeSort}}
        )
)

Я пробовал пару подходов (мне потребовалось почти 8 часов, чтобы добраться до)

/({{([^\/].[^ ]*)(?:.[^ ][^{{]+)}})(?:(?=([^{{]+))\3|{{(?!\2[^}}]*}}))*?({{\/\2}})/

AND, more recently...

/({{([^\/].[^ ]*)(?:.[^ ][^{{]+)}})((?:(?!\{\{|\}\}).)++|(?R)*)({{\/\2}})/

Я ни в коем случае не гуру с регулярным выражением, я на самом деле просто изучил его за последний день или около того, пытаясь заставить это работать.Я гуглил по этому поводу и понимаю, что регулярное выражение не предназначено для вложенных вещей, но (? R), кажется, делает трюк на простых примерах скобок, которые я видел в интернетах, но они всегда учитывают только вещи между{и} или (и) или <и>.Прочитав почти весь веб-сайт с информацией о регулярных выражениях и играя, я пришел к этим двум версиям.

Так что, что мне НУЖНО сделать (я думаю), сначала нужно будет выполнить регулярное выражение из тега иерархии DEEPEST, иработать его выход (если я могу сделать это с помощью php, это нормально для меня).Я думал найти самый глубокий слой, получить его данные и работать в обратном направлении, пока все содержимое не окажется в 1 толстом массиве.Я предположил, что это то, что ($ R) собирался сделать для меня, но это не так.

Так что любая помощь в том, что я пропускаю, будет большой, также примите во внимание, что моя, кажется, имеетпроблемы с {{}}, которые НЕ имеют конечной версии.Так что, как и мой {{Случайный}} пример, был удален ради того, чтобы я проанализировал пример массива.Я чувствую, что эти теги вместе с тегами $ {} можно оставить в покое (если бы я знал, как это сделать с помощью регулярных выражений) и просто оставить в тексте там, где они есть.Я более или менее интересуюсь функциями и передачей их данных в многомерный массив для дальнейшей работы с ними.

Извините за длинный пост, я просто всю ночь бился с этим головой.Я начал с предположения, что это будет немного проще ... Пока я не понял теги, где вложенные: /

Любая помощь приветствуется!Спасибо!

Ответы [ 3 ]

1 голос
/ 13 января 2012

Ух ты, какой странный синтаксис шаблонов.

Метод, который я, вероятно, использовал бы для решения этой проблемы, будет выглядеть примерно так:

  • Используйте простое регулярное выражение, чтобы изменить все *От 1006 * до <tags>
  • Используйте другое простое регулярное выражение для преобразования разделенных пробелами аргументов / условий внутри тегов в синтаксис XML-подобного атрибута (например, {{foo bar !baz}} станет <foo arg1="bar" arg2="!baz"> или подобным)
  • Обработайте его как DOMDocument .

Получайте удовольствие.: -)

0 голосов
/ 30 января 2012

Спустя немного времени, работая над ним, я, в конечном счете, узнал больше о регулярных выражениях и теперь понимаю его в T.Самое замечательное в том, что у PHP есть (? R), и теперь я понимаю, почему он выглядит так.lol

В конце концов, регулярное выражение, с которым я работал, появилось на странице php, объясняющей рекурсив (? R).Затем я просто работал над получением тегов regex вместо круглых скобок, которые они использовали в примере.

Я знаю, что мне нужен самый внутренний тег, но, конечно, можно выполнить то же самое с внешним тегом, так чторегулярное выражение делает именно это.Он находит и захватывает самый внешний {{tag (thatMightHaveDataHere)}}} и имеет внутреннее содержимое, которое может быть больше {{TAGS}} внутри него. {{/ Tag}}

Вот оно,

/{{([\w]+) ?([^}]*?)(?:}}((?:[^{]*?|(?R)|{{[\w]*?}}|\${.*?})*){{\/\1}})/ 

0 = Соответствующий «внешний тег» 1 = Найденный тег, т. Е. {{Tag}} {{/ \ 1}} 2 = Любые данные после первого пробела внутри тега, т. Е. {{TagThisDataIs StoredAs2}} 3 = ВНУТРЕННИЙ Контент (который может быть рекурсивным для этого регулярного выражения, или бесконечный тег {{noEndTag}}, или тег, начинающийся с доллара $ {likeThis}

Выполнить циклна $ match [3] с этим регулярным выражением, и вы можете циклически находить их. Не уверен, где вы будете использовать это за пределами того, для чего мне это было нужно, но я уверен, что кто-то может изменить его, если ему нужно, чтобы он работал над другимиструктура вложенного стиля.

0 голосов
/ 13 января 2012

Внимание! Вы пытаетесь написать парсер только с регулярными выражениями. Это не очень хорошо работает. Почему бы и нет? Потому что вам нужно хранить также состояние !

Так что тогда? Ну ты парсер конечно пишешь: D

Если вам нужны советы о том, как начать, я могу помочь, но я бы посоветовал вам сначала попробовать это самостоятельно. Как работает парсер? :)

* * 1010

Токенизация вашего ввода И преобразовать его во вложенное дерево так:

array(
    array("code", "FunctionTag (Condition?)", array(
        "<div>This is an ",
        array("code", "CheckOfSomeSort someTimesThese !orThese", array(
            "example of some ",
            array("code", array("Random"), array()),
            " data"
        )),
        " that will be ${worked} on</div>"
    ))
)

Теперь вам просто нужно интерпретировать части кода и получить ожидаемый результат. Вы также можете добавить такие вещи, как номера строк и позиции символов, что очень полезно для отладки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...