PHP 正则 Unicode 模式的影响
在模式末尾加上对应的修饰符后,PCRE 进入 UTF-8 模式:模式与主题串按 UTF-8 解析,点号与量词按字符而不是按字节作用,中文与表情符号的处理方式随之改变。要特别注意两点:主题串不是合法 UTF-8 时函数会直接返回假值,而这个修饰符并不会让单词类与数字类自动覆盖非 ASCII 字符。
基本信息
| 开启方式 | 在末尾定界符后追加对应修饰符 |
|---|---|
| 解析单位 | 按字符解析模式与主题串,点号与量词作用于完整字符 |
| 前置条件 | 模式与主题串都必须是合法 UTF-8,否则出错并返回假值 |
| 能力边界 | 单词类与数字类仍按 ASCII 解释,需要按 Unicode 判定时使用属性转义 |
典型使用场景
- 中文内容校验:按字符数而不是字节数判断长度与格式
- 多语言输入处理:处理变音字母与其他语言字母时改用属性转义配合该修饰符
- 表情符号处理:按字符匹配与截断,避免截断到半个字符
- 属性匹配:按脚本或字符类别筛选内容,例如只保留汉字
- 数据清洗:从不同来源汇聚文本时先统一编码,再启用该修饰符
行为差异示例
行为差异示例
preg_match('/^.{2}$/u', '两个'); // 命中:点号按字符匹配
preg_match('/^.{2}$/', '两个'); // 不命中:一个汉字占三个字节
preg_match('/^.{2}$/u', "\xC3\x28"); // 返回假值:主题串不是合法 UTF-8
if (preg_match('/^\w+$/u', '中文') !== 1) { /* 仍然不匹配,\w 是 ASCII 语义 */ }
preg_match('/^\p{Han}+$/u', '中文'); // 按脚本属性匹配汉字
preg_match('/\p{L}+/u', 'café'); // 按字母属性匹配,含变音字母
// 出错时查看错误码定位原因
$err = preg_last_error(); // 无效 UTF-8 与限额超限对应不同常量开启前后的差异
| 项目 | 未开启 | 开启后 |
|---|---|---|
| 解析单位 | 按字节 | 按字符 |
| 点号作用对象 | 单个字节 | 单个字符 |
| 非法编码主题串 | 按字节继续处理 | 返回假值并置错误码 |
| 单词类与数字类 | ASCII 语义 | 仍为 ASCII 语义 |
| 属性转义 | 不可用 | 可用,需配合该修饰符 |
字符串长度函数与偏移量仍按字节计算,因此「按字符数限制长度」不能直接用字节长度判断,需要改用多字节字符串函数;这一点在存储字段长度与前端提示之间也常出现不一致。
主题串编码不合法时函数返回假值而不是「不匹配」,缺少严格返回值判断会导致校验被静默跳过,形成安全漏洞;入口处应统一校验并规范化编码。