Справка / объяснение по регулярным выражениям PHP

#php #regex

#php #регулярное выражение

Вопрос:

До сих пор мне успешно удавалось избегать очень многого с регулярными выражениями, кроме проверки правильности адреса электронной почты. Однако, как часть более крупного университетского проекта, я разрабатываю простой движок tempting и пытаюсь реализовать свой собственный простой синтаксис для обработки циклов и, в конечном итоге, операторов IF вместо включения PHP в мои файлы шаблонов. Я знаю, что многие люди скажут, не беспокойтесь или просто используйте существующую систему, но поскольку это для моей диссертации, я хочу, чтобы как можно больше из этого было моей собственной работой!

В любом случае, вернемся к проблеме. В качестве примера у меня есть следующий код в файле моего шаблона:

 <p>Template Header</p>
{{foreach{array1}}}
    <p>This is the first content line that should be displayed.</p>
{{/foreach}}
{{foreach{array2}}}
    <p>This is the second content line that should be displayed.</p>
{{/foreach}}
<p>Template Footer</p>
  

Затем я получил следующий PHP для чтения файла, поиска циклов и их извлечения.

 <?php
$template = file_get_contents('reg.html');
$expression = "#.*{{foreach{(.*?)}}}(.*?){{/foreach}}.*#is";
$result = preg_replace($expression, "$1", $template);  
var_dump($result);
?>
  

При вызове preg_replace и выгрузке результата $ 1 дает мне имя массива, которое будет использоваться для цикла (array1 или array2), затем изменение его на $ 2 даст мне содержимое между тегами цикла. Идеальный. Проблема в том, что это работает только для одного тега {{foreach}}.

Могу ли я в любом случае зациклить все совпадения регулярного выражения, чтобы получить результаты, которые я получаю выше? Любая помощь / совет очень ценится — но go easy regex для меня довольно новое!

Комментарии:

1. Это неподходящая задача для регулярных выражений. У вас будет жестокое время, как только вы попытаетесь вложить foreach или if заблокировать. Вам нужно написать настоящий синтаксический анализатор, а не собирать что-то вместе, злоупотребляя регулярными выражениями.

Ответ №1:

 $expression = "#.*{{foreach{(.*?)}}}(.*?){{/foreach}}.*#is";
                ^^                                   ^^
  

Вы не просто сопоставляете тег шаблона «foreach», но и все, что до и после него. Это означает, что второй foreach тоже будет поглощен .* . Таким образом, вы не можете сопоставить его снова.

Комментарии:

1. Вы можете добавить, что, в частности, совпадение будет соответствовать всей строке, если она содержит один из этих foreach блоков, а затем заменить всю строку содержимым foreach блока. То есть заменяется , а не просто съедается.