s修饰符使点号.匹配包括换行符在内的所有字符;默认情况下.不匹配换行符,导致跨行匹配失败,常见于HTML、JSON等多行文本处理场景。

PHP正则修饰符 s 的作用是:让点号 . 匹配包括换行符 \n 在内的所有字符。 不加 s 时,. 默认只匹配除换行符以外的任意字符——这是绝大多数人踩坑的根源。
为什么 s 修饰符常被误用或遗漏
常见错误现象是:写了一个看似能跨行匹配的正则,比如 /div>(.*?)/,但目标 HTML 片段含换行(如 <div>\n content\n</div>),结果完全不匹配或只匹配到第一行。
- 根本原因:默认情况下
.遇到\n就停住,不会“穿透”换行 - 不是正则写错了,而是引擎行为没对上预期
- 尤其在处理 HTML、JSON 多行字符串、日志块时,漏掉
s就等于放弃跨行能力
s 和 m 修饰符的区别与组合场景
s 控制 . 是否吃换行;m 控制 ^ 和 $ 是否锚定每行首尾——两者解决的是不同问题,但经常一起出现。
- 只用
m:对^abc$这类逐行匹配有用,但.依然跳不过\n - 只用
s:能让.*吃掉换行,但^和$仍只锚定整个字符串头尾 - 常用组合
/pattern/ms:既支持跨行捕获(靠s),又支持行内锚定(靠m),比如提取多行块中某一行开头的字段
替代方案:[sS] 能不用 s 吗
可以,但不推荐作为常规做法。例如 /div>([sS]*?)/ 确实能绕过 s 修饰符,原理是 [sS] 中 s 匹配空白(含 \n),S 匹配非空白,合起来覆盖全部字符。
立即学习“PHP免费学习笔记(深入)”;
- 优点:不用改修饰符,适合临时 patch 或某些不支持
s的旧环境 - 缺点:可读性差、性能略低(字符类比单个
.开销稍大)、容易写成[.S]或[s.]这类无效写法 - 注意:
[sS]是字符类,s和S都是字面量含义,不是修饰符——别和修饰符s混淆
真正容易被忽略的是:哪怕你用了 s,如果正则里混用了贪婪量词(比如 .*)而没加 ?,它还是会一口气吞到末尾再回溯,导致捕获内容远超预期。这时候得配合非贪婪 .*? 或更精确的否定字符类(如 [^)来收口。



















