在PHP preg_replace函数中包含新行

时间:2009-03-29 23:41:58

标签: php regex newline

我正在尝试匹配可能出现在多行上的字符串。它以特定字符串开头和结尾:

{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 个答案:

答案 0 :(得分:32)

使用s modifier

$template = preg_replace( $'/\{a\}([.\n]+)\{\/a\}/s', 'X', $template, -1, $count );
//                                                ^
echo $count;

答案 1 :(得分:7)

我认为你遇到的问题多于不匹配换行符的点,但让我先从格式化推荐开始。您可以使用任何标点字符作为正则表达式分隔符,而不仅仅是斜杠('/')。如果使用其他字符,则不必在正则表达式中转义斜杠。我知道'%'在PHPers中很受欢迎;这将使您的模式参数:

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

现在,正则表达式没有按预期工作的原因是因为当点出现在字符类(方括号)中时,点失去了它的特殊含义 - 所以[.\n]只匹配一个点或一个点换行。您要找的是(?:.|\n),但我建议匹配回车符和换行符:

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

这是因为单词“newline”可以指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,但这看起来像是一个语法错误。如果有人可以在这件事上教育我,我会很感激。

答案 2 :(得分:3)

来自http://www.regular-expressions.info/dot.html

  

“点匹配单个字符,   没有关心那个角色是什么。   唯一的例外是换行符   字符“。

您需要在表达式中添加一个尾随/ s标志。