Шаблон ifs с использованием регулярного выражения

Привет всем, я работаю над приложением PHP, которое должно анализировать файл .tpl с HTML в нем, и я делаю так, чтобы HTML мог иметь переменные и базовые операторы if в нем. Оператор if выглядит примерно так: `

<!--if ({VERSION} == 2)-->
Hello World
<!--endif -->

Чтобы разобрать это, я безуспешно пытался использовать preg_replace. Шаблон, который я пробовал, был

/<!--if\(([^\]*)\)-->([^<]*)<!--endif-->/e

который заменяется на

if ($1) { echo "$2"; }

Есть идеи, почему это не сработает и что я могу сделать, чтобы запустить его?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
400
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

У вас есть пробел между endif и -->, но ваше регулярное выражение не позволяет этого.

Между прочим, это кажется ужасно небезопасным ... Есть ли причина, по которой вы не используете заранее созданный движок шаблонов, такой как Smarty?

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

'/<!--if\(([^\\\]*)\)-->([^<]*)<!--endif-->/e'

Но я не знаю, зачем вы изобретаете новую структуру логики шаблонов, когда существуют такие решения, как Smarty и сам PHP.


Вот тестовый код в ответ на комментарии ниже.

testinput.tpl:

<!--if ({VERSION} == 2)-->
Hello World
<!--endif-->

match.php:

<?php
$template = file_get_contents('testinput.tpl');
print preg_match('/<!--if\(([^\\\]*)\)-->/e', $template) . "\n";
print preg_match('/<!--endif-->/e', $template) . "\n";
print preg_match('/<!--if\(([^\\\]*)\)-->([^<]*)<!--endif-->/e', $template) . "\n";

тестовый забег:

$ php match.php
1
1
1

Я собирался задать точно такой же вопрос ... Так что я просто поддерживаю ваше! ;-)

PhiLho 23.12.2008 23:55

Три обратной косой черты - это так же плохо, как и одна, Билл; вы все еще избегаете квадратной скобки.

Alan Moore 24.12.2008 01:00

Действительно? Я только что запустил его, и он вернул положительное совпадение с вводом. А с одной или двумя обратными косыми чертами выдает ошибку о несбалансированной квадратной скобке.

Bill Karwin 24.12.2008 01:01

Хм. С четырьмя обратными косыми чертами он также возвращает положительное совпадение.

Bill Karwin 24.12.2008 01:02

Как вы это тестируете и что содержали группы захвата? Я попробовал это в поле поиска EditPad, ошибок не было, но ничего не найдено. Java даже не примет его с нечетным количеством обратных косых черт.

Alan Moore 24.12.2008 01:39

Я не могу протестировать PHP напрямую, но я пробовал это в некоторых онлайн-тестерах регулярных выражений PHP, и он работает с двумя обратными косыми чертами, но не с одним или тремя. Не то чтобы это важно; в этом классе символов не должно быть обратной косой черты. Просто правая скобка.

Alan Moore 24.12.2008 06:28
Ответ принят как подходящий

Я думаю, вы хотели это сделать:

'/<!--if\(([^)]*)\)-->([^<]*)<!--endif-->/'

В вашем регулярном выражении есть только один класс символов:

[^\]*)\)-->([^<]

Вот что происходит:

  • Первая закрывающая квадратная скобка экранирована обратной косой чертой, поэтому она соответствует буквально.
  • Круглые скобки, которые должны были закрывать первую группу захвата и открывать вторую, также воспринимаются буквально; внутри символьного класса нет необходимости экранировать парные скобки.
  • Первый дефис является взят как метасимвол; он формирует диапазон [) * +, -]
  • Вторая открывающая квадратная скобка воспринимается как буквальная квадратная скобка, потому что она находится внутри класса символов.
  • Вторая вставка считается буквальной, потому что это не первый символ в классе.

Итак, после удаления дубликатов и сортировки символов в их порядке ASCII ваш класс символов эквивалентен этому:

[^()*+,\-<>\[\]^]

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

Другие вопросы по теме