我正在尝试匹配可能出现在多行上的字符串。它以特定字符串开头和结尾:
{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当他们独立时,但不在一起!
答案 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标志。