Включение новых строк в функцию PHP preg_replace - PullRequest
14 голосов
/ 30 марта 2009

Я пытаюсь сопоставить строку, которая может появляться в нескольких строках. Он начинается и заканчивается определенной строкой:

{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 ]

32 голосов
/ 30 марта 2009

Используйте модификатор s :

$template = preg_replace( $'/\{a\}([.\n]+)\{\/a\}/s', 'X', $template, -1, $count );
//                                                ^
echo $count;
7 голосов
/ 30 марта 2009

Я думаю, что у вас больше проблем, чем просто точка, не совпадающая с новой строкой, но позвольте мне начать с рекомендации по форматированию. В качестве разделителя регулярных выражений можно использовать практически любой знак пунктуации, а не только косую черту ('/'). Если вы используете другого персонажа, вам не придется избегать косых черт в регулярном выражении. Я понимаю, что "%" популярен среди PHPеров; это сделало бы ваш аргумент шаблона:

'%\{a\}([.\n]+)\{/a\}%'

Теперь, причина того, что регулярное выражение не сработало так, как вы предполагали, заключается в том, что точка теряет свое особое значение, когда появляется внутри класса символов (квадратные скобки) - так что [.\n] просто соответствует точке или переводу строки. Вы искали (?:.|\n), но я бы порекомендовал сопоставить возврат каретки и перевод строки:

'%\{a\}((?:.|[\r\n])+)\{/a\}%'

Это потому, что слово "новая строка" может относиться к Unix-стилю "\ n", Windows-стилю "\ r \ n" или старому-Mac-стилю "\ r". Любая данная веб-страница может содержать любой из них или смесь двух или более стилей; сочетание "\ n" и "\ r \ n" очень распространено. Но с режимом / s (также известным как однострочный или режим DOTALL) вам не нужно беспокоиться об этом:

'%\{a\}(.+)\{/a\}%s'

Однако есть еще одна проблема с оригинальным регулярным выражением, которое все еще присутствует в этом: + является жадным. Это означает, что если в тексте более одной последовательности {a}...{/a}, то при первом применении вашего регулярного выражения оно будет соответствовать всем из них, от первого {a} до последнего {/a}. Самый простой способ исправить это - сделать + неловким (a.k.a, "ленивый" или "неохотно"), добавив знак вопроса:

'%\{a\}(.+?)\{/a\}%s'

Наконец, я не знаю, что делать с '$' перед открывающей кавычкой вашего аргумента шаблона. Я не делаю PHP, но это похоже на синтаксическую ошибку для меня. Если бы кто-то мог научить меня этому вопросу, я был бы признателен.

3 голосов
/ 30 марта 2009

С http://www.regular -expressions.info / dot.html :

"Точка соответствует одному символу, не заботясь о том, что это за персонаж. Единственным исключением являются перевод строки символы ".

вам нужно будет добавить трейлинг / s флаг к вашему выражению.

...