#php #regex #block
#php #регулярное выражение #блок
Вопрос:
Я пытаюсь написать (я думаю) довольно простое регулярное выражение с помощью PHP, но это не работает. В принципе, у меня есть блок, определенный следующим образом:
%%%%blockname%%%%
stuff goes here
%%%%/blockname%%%%
Я не силен в регулярных выражениях, но это то, что я пробовал:
preg_match_all('/^%%%%(.*?)%%%%(.*?)%%%%/(.*?)%%%%$/i',$input,$matches);
Он возвращает массив с 4 пустыми записями.
Я предполагаю, что ему также, помимо фактической работы, нужен какой-то указатель для третьего совпадения, потому что он должен быть равен первому?
Пожалуйста, просветите меня
Комментарии:
1. Если у вас нет вложенных блоков, вам не нужно беспокоиться о том, что третье совпадение совпадает с первым. С другой стороны, если у вас есть вложенные блоки, регулярные выражения могут оказаться неподходящим вариантом..
2. У меня нет вложенных блоков прямо сейчас, но могут появиться в будущем. Я также думал о том, чтобы, возможно, использовать вместо этого анализатор HTML и определять блоки, предоставляя атрибуты моему HTML-коду.
Ответ №1:
Вам нужно разрешить совпадение точки с новой строкой и разрешить совпадение ^
и $
в начале и конце строк (а не только всей строки):
preg_match_all('/^%%%%(.*?)%%%%(.*?)%%%%/(.*?)%%%%$/sm',$input,$matches);
s
(Однострочный) параметр позволяет использовать точку в соответствии с любым символом, включая новые строки.
m
(Многострочный) параметр позволяет ^
и $
совпадать в начале и в конце строк.
i
Опция не нужна в вашем регулярном выражении, поскольку в нем нет символов, чувствительных к регистру.
Затем, чтобы ответить на вторую часть вашего вопроса: если blockname
в обоих случаях одно и то же, то вы можете сделать это явным, используя обратную ссылку на первую группу захвата:
preg_match_all('/^%%%%(.*?)%%%%(.*?)%%%%/1%%%%$/sm',$input,$matches);
Комментарии:
1. Хороший момент, хотя на самом деле это не ответ на вопрос Кокоша.
2. Я полагаю,
1
тогда имеется в виду первый матч, учись чему-то каждый день![]()
3.
n
относится к содержимомуn
-й группы захвата (набор круглых скобок) в регулярном выражении. В другом комментарии вы упомянули, что в будущем у вас могут появиться вложенные блоки. Здесь все становится сложнее. Это можно сделать, но это, мягко говоря, сложно.4. Я обнаружил проблему с моим вводом HTML,
%%%%blockname%%%%
был сделан отступ, поэтому, я думаю,^
не разрешил сопоставлять его, потому что это не было первым в строке.5. В этом случае просто добавьте
s*
после^
и / или перед$
.
Ответ №2:
Я почти уверен, что вы не можете, поскольку для этих операций потребуется сохранить переменную, а вы не можете в регулярном выражении. Вам следует попробовать сделать это с помощью встроенного в PHP анализатора токенов. http://php.net/manual/en/function .token-get-all.php
Комментарии:
1. что вы имеете в виду, что вы не можете сохранить переменную в регулярном выражении? Я не думаю, что я что-то упускаю, когда говорю, что
$matches
будет содержать то, что соответствует.2.
$matches
является PHP. Но если вы не хотите использовать regex для сопоставления открывающего и закрывающего тегов, вам придется сохранить первый тег и выполнить поиск только по соответствующему закрывающему тегу (вместо любого закрывающего тега).3. Я не уверен, что я вас неправильно понял, но ответ, который дал Тим Пьецкер, действительно позволяет мне сопоставлять открывающий и закрывающий теги в одном регулярном выражении (и я не могу понять, почему это не должно быть возможно в первую очередь).
4. Пожалуйста, перечитайте вопрос. Он запрашивает регулярное выражение, которое может обнаружить соответствующий (вложенный) закрывающий тег. (пример:
<a> ... </a>
,<a> ... <b> ... </b> ... </a>
, выдал быa ... b
вместоb ... b ... a ... a
)