Ответ 1
Используйте s
модификатор:
$template = preg_replace( $'/\{a\}([.\n]+)\{\/a\}/s', 'X', $template, -1, $count );
// ^
echo $count;
Я пытаюсь сопоставить строку, которая может отображаться в нескольких строках. Он начинается и заканчивается определенной строкой:
{a}some string
can be multiple lines
{/a}
Могу ли я взять все между {a}
и {/a}
с помощью регулярного выражения? Кажется. не соответствует новым строкам, но я не пробовал следующее:
$template = preg_replace( $'/\{a\}([.\n]+)\{\/a\}/', 'X', $template, -1, $count );
echo $count; // prints 0
Он соответствует. или \n, когда они сами по себе, но не вместе!
Используйте s
модификатор:
$template = preg_replace( $'/\{a\}([.\n]+)\{\/a\}/s', 'X', $template, -1, $count );
// ^
echo $count;
Я думаю, у вас больше проблем, чем просто точка, не соответствующая новой строке, но позвольте мне начать с рекомендации по форматированию. Вы можете использовать практически любой символ пунктуации как разделитель регулярных выражений, а не только косую черту ('/'). Если вы используете другого персонажа, вам не придется скрывать косые черты в регулярном выражении. Я понимаю, что "%" популярен среди PHPers; что сделало бы ваш шаблонный аргумент:
'%\{a\}([.\n]+)\{/a\}%'
Теперь причина, по которой регулярное выражение не работает так, как вы намеревались, состоит в том, что точка теряет свое особое значение, когда она появляется внутри класса символов (квадратные скобки) - поэтому [.\n]
просто соответствует точке или строке. То, что вы искали, было (?:.|\n)
, но я бы рекомендовал сопоставить возврат каретки, а также строку перевода:
'%\{a\}((?:.|[\r\n])+)\{/a\}%'
Это потому, что слово "новая линия" может ссылаться на стиль "\n" в стиле Unix, стиль "\ r\n" в стиле Windows или более старый стиль "\ r". Любая данная веб-страница может содержать любую из них или смесь из двух или более стилей; сочетание "\n" и "\ r\n" очень распространено. Но с режимом /s (также называемым однострочным или DOTALL-режимом) вам не нужно беспокоиться об этом:
'%\{a\}(.+)\{/a\}%s'
Однако существует еще одна проблема с исходным регулярным выражением, которое все еще присутствует в этом: +
является жадным. Это означает, что если в тексте присутствует более одной {a}...{/a}
последовательности, при первом применении регулярного выражения он будет соответствовать всем им, начиная с первого {a}
и до последнего {/a}
. Самый простой способ исправить это, чтобы сделать +
ungreedy (a.k.a, "ленивый" или "неохотный" ), добавив знак вопроса:
'%\{a\}(.+?)\{/a\}%s'
Наконец, я не знаю, что делать с '$' перед открывающей цитатой вашего аргумента шаблона. Я не делаю PHP, но это выглядит как синтаксическая ошибка для меня. Если бы кто-то мог воспитывать меня в этом вопросе, я был бы признателен.
От http://www.regular-expressions.info/dot.html:
"Точка соответствует одному символу, не заботясь о том, что это за символ. Единственное исключение - новая строка символы".
вам нужно будет добавить к вашему выражению флаг trailing/s.