Включение новых строк в функцию замены PHP preg
Я пытаюсь сопоставить строку, которая может отображаться в нескольких строках. Он начинается и заканчивается определенной строкой:
{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, когда они сами по себе, но не вместе!
3 answers
Используйте 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" в стиле более старых компьютеров Mac. Любая данная веб-страница может содержать любой из них или смесь двух или более стилей; сочетание "\n" и "\r\n" является очень распространенный. Но в режиме /s (также известном как однострочный или точечный режим) вам не нужно беспокоиться об этом:
'%\{a\}(.+)\{/a\}%s'
Однако есть еще одна проблема с исходным регулярным выражением, которая все еще присутствует в этом: +
является жадным. Это означает, что если в тексте более одной последовательности {a}...{/a}
, при первом применении вашего регулярного выражения оно будет соответствовать всем из них, от первого {a}
до последнего {/a}
. Самый простой способ исправить это - сделать +
нескладным (он же "ленивый" или "неохотно"), добавив знак вопроса:
'%\{a\}(.+?)\{/a\}%s'
Наконец, я не знаю, что делать с "$" перед вступительной цитатой вашего аргумента шаблона. Я не занимаюсь PHP, но для меня это выглядит как синтаксическая ошибка. Если бы кто-нибудь мог просветить меня в этом вопросе, я был бы признателен.
Из http://www.regular-expressions.info/dot.html:
"Точка соответствует одному символу, не заботясь о том, что это за символ. Единственным исключением являются символы новой строки"
.
Вам нужно будет добавить флаг завершения /s к вашему выражению.