PHP регулярное сопоставление регулярных выражений - PullRequest
0 голосов
/ 21 сентября 2009

Я пытаюсь сопоставить определенный набор тегов в файле шаблона. Однако я хочу, чтобы теги были может быть вложенным в себя.

Мое регулярное выражение выглядит следующим образом: (с / с)

<!-- START (.*?) -->(.*?)<!-- END \\1 -->

Пример тега:

<!-- START yList -->
  y:{yList:NUM} | 
  <!-- START xList -->
    x:{xList:NUM} 
  <!-- END xList -->
  <!-- CARET xList -->
  <br>
<!-- END yList -->
<!-- CARET yList -->

Прямо сейчас результат матчей будет:

соответствует 0:

группа (0) (весь матч)

<!-- START yList --> 
 y 
 <!-- START xList --> 
   x 
 <!-- END xList --> 
 <!-- CARET xList --> 
 <br> 
<!-- END yList -->

группа (1)

yList

группа (2) * +1021 *

y 
<!-- START xList --> 
  x 
<!-- END xList --> 
<!-- CARET xList --> 
<br>

Я хочу 2 совпадения вместо 1, очевидно, набор вложенных тегов не совпадает. Возможно ли это с помощью regex, или я должен просто сохранить результаты regexing group (2), пока я не нашел новых совпадений?

Ответы [ 2 ]

5 голосов
/ 21 сентября 2009

Регулярные выражения не подходят для анализа древовидных структур произвольной глубины. Это может быть возможно, в зависимости от используемого вами выражения regex, но не рекомендуется - их сложно читать и отлаживать.

Я бы предложил вместо этого написать простой парсер. Что вы делаете, это разлагаете свой текст на набор возможных токенов , каждый из которых может быть определен простыми регулярными выражениями, например ::

START_TOKEN = "<!-- START [A-Za-z] -->"
END_TOKEN = ...
HTML_TEXT = ...

Итерация по вашей строке, и, пока вы сопоставляете эти токены, извлекайте их из строки и сохраняйте их в отдельном списке. Обязательно сохраните текст, который был внутри токена (если есть), когда вы делаете это.

Затем вы можете перебирать свой список токенов, и на основе типов токенов вы можете создать вложенную древовидную структуру узлов, каждый из которых содержит либо 1) текст исходного токена, и 2) список дочерних узлов.

Возможно, вы захотите взглянуть на некоторые руководства по синтаксическому анализу, если это кажется слишком сложным.

0 голосов
/ 21 сентября 2009

Вы можете сделать что-то вроде этого:

$parts = preg_split('/(<!-- (?:START|END|CARET) [a-zA-Z][a-zA-Z0-9]* -->)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
$tokens = array();
$isTag = isset($tokens[0]) && preg_match('/^<!-- (?:START|END|CARET) [a-zA-Z][a-zA-Z0-9]* -->$/', $tokens[0]);
foreach ($parts as $part) {
    if ($isTag) {
        preg_match('/^<!-- (START|END|CARET) ([a-zA-Z][a-zA-Z0-9]*) -->$/', $token, $match);
        $tokens[] = array($match[1], $match[2]);
    } else {
        if ($token !== '') $tokens[] = $token;
    }
    $isTag = !$isTag;
}
var_dump($tokens);

Это даст вам структуру вашего кода.

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