PHP正则跨行匹配怎么写
轻涛姑娘_9487
发布时间:2026-08-31 22:50:16
|
935人浏览过
|
来源于php中文网
原创
PHP preg_match默认不跨行,因.不匹配换行符;加s修饰符可使.匹配包括\n在内的所有字符,解决多行匹配失败问题。

PHP preg_match 默认不跨行?加 s 修饰符
PHP 的 PCRE 正则默认把换行符(\n)当成字符串边界,. 不会匹配它。所以写 /.+/ 这种看似能“匹配任意内容”的模式,遇到换行就停了。解决方法很简单:在正则末尾加上 s(single-line)修饰符,让 . 能匹配包括换行在内的所有字符。
常见错误现象:preg_match('/<div>(.+)/s', $html, $m) 不加 <code>s 时,如果 <div> 和 <code>
之间有换行,就完全匹配不上。
-
s 修饰符只影响 . 的行为,不影响 ^ 和 $(它们仍锚定整串开头/结尾,除非同时加 m)
- 不要和
m(multiline)混淆:m 改变的是 ^/$,不是 .
- 若只需匹配换行本身,不用
s,直接写 \n 或 [\r\n] 更明确
多行文本中匹配带换行的结构,比如 HTML 片段
真实场景里,你往往不是想“匹配任意跨行内容”,而是想提取一段包含换行的块,比如多行 <pre class="brush:php;toolbar:false;"></code> 标签、缩进的 JSON、或模板中的注释块。这时光靠 <code>.</code> + <code>s</code> 容易过度匹配(贪婪),得配合非贪婪量词或更精确的边界。</p><p>例如提取 <code><!-- ... --></code> 多行注释:</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/7fc7563c4182" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">PHP免费学习笔记(深入)</a>”;</p><pre class='brush:php;toolbar:false;'>preg_match('/<!--(.*?)-->/s', $content, $m);</pre><p>注意这里用了 <code>.*? 而不是 .*,避免从第一个 <!-- 一直吃到文件末尾最后一个 -->。
- 用
.*? 配合 s 是最常用组合,但性能略差于明确字符集(如 [^)
- 若目标结构有固定起始/结束标记(如
```json 和 ```),优先用它们做边界,比依赖 . 更安全
- 嵌套结构(如多层
<div>)无法用正则可靠处理,此时该换 DOM 解析器<h3>
<code>preg_match_all 跨行匹配多个块时的注意事项
当用 preg_match_all 提取多个跨行块(比如日志里的多段错误堆栈),容易踩两个坑:一是忘记 s,二是没控制好匹配范围导致重叠或截断。
比如匹配形如 [ERROR] ... \n... \n[/ERROR] 的块:
preg_match_all('/\[ERROR\](.*?)\[\/ERROR\]/s', $log, $matches);这个写法在大多数情况下可行,但如果 [ERROR] 和 [/ERROR] 之间也含 [/ERROR] 字样(比如嵌套或误写),就会提前终止。这时候需要更严格的分隔逻辑。
- 确保结束标记足够唯一,必要时转义特殊字符,如
\[\/ERROR\]
- 如果数据源可控,建议用不可见分隔符(如
\x01)替代文本标记,彻底避开正则歧义
-
preg_match_all 的 PREG_SET_ORDER 标志能让结果按匹配块组织,比默认的 PREG_PATTERN_ORDER 更易处理
为什么不用 [\s\S] 替代 . + s?
有些老代码会看到 [\s\S] 或 [\d\D] 这种写法,意图是“匹配所有空白+非空白 = 所有字符”,确实能绕过 s 修饰符限制。但它本质是取巧,且有隐患。
问题在于:\s 在不同 PCRE 版本或 u(UTF-8)修饰符下可能包含或排除某些 Unicode 空白(如 、Zs 类字符),而 . + s 行为是明确定义的:匹配除换行符外的所有字符(加 s 后连换行也包括)。
- 用
[\s\S] 会让正则变长、可读性下降,还可能引入编码兼容性问题
- PHP 7.3+ 对
s 修饰符支持稳定,没必要倒退用兼容写法
- 唯一适合
[\s\S] 的场景是:你明确需要排除某类字符(比如跳过制表符),但这种情况极少
跨行匹配的核心就一条:需要 . 匹配换行,必须加 s;其余都是围绕它控制精度和边界的问题。别被各种“技巧”带偏,先确保修饰符正确,再谈优化。