PHP多行模式正则匹配捕获内容意外包含换行符问题排查
问题根因
你遇到的问题源于PHP PCRE正则引擎对行结束符的默认处理规则:
- PCRE中
.默认仅排除换行符\n(LF),回车符\r(CR)会被.正常匹配。你的测试数据使用Windows风格换行\r\n,第一行实际内容为!!! hello\r\n - 多行模式(
m修饰符)下,PCRE默认仅将\n作为行结束标记,$锚点默认只匹配\n之前的位置。因此.*会贪婪匹配到\n前的所有内容,包含末尾的\r,你实际捕获到的是hello\r而非hello\r\n - 输出时
\r会被多数文本渲染环境当作回车/换行处理,因此会看到第二个|出现在新行,看起来像是捕获了换行符。
你修改为[a-z]*后能正常输出,正是因为\r不在小写字母匹配范围内,捕获到hello后就停止了,不会包含末尾的\r;限定结尾为o的版本同理。
解决方案
以下任意一种方案都可以解决该问题:
- 方案1:直接在捕获组中排除所有换行相关字符,从根源上避免匹配到
\rpreg_replace('/^!!! ([^\r\n]*)/m', '|$1|', $content); - 方案2:在正则开头添加
(*CRLF)标记,告诉PCRE引擎将\r\n作为行结束标记,此时$锚点会匹配\r\n之前的位置,不会把\r留给捕获组preg_replace('/(*CRLF)^!!! (.*)$/m', '|$1|', $content); - 方案3:先统一将内容的换行符转为Unix风格的
\n,再执行正则匹配$content = str_replace("\r\n", "\n", $content); preg_replace('/^!!! (.*)$/m', '|$1|', $content);
内容的提问来源于stack exchange,提问作者Tarindel
相关产品推荐
相关产品推荐

