preg_match_all 不可用于统计字符串长度,它专用于匹配并返回所有匹配项数量;正确做法是:ASCII 用 strlen,UTF-8 多语言用 mb_strlen($str, 'UTF-8')。

别用 preg_match_all 统计字符串长度——它根本不是干这个的,强行用只会引入 bug、性能损耗和编码困惑。
为什么 preg_match_all 不该用来“算长度”
这个函数本意是「匹配并返回所有匹配项的数量」,不是「统计字符数」。它受正则模式影响极大,比如:
-
/./u看似能逐字符匹配,但遇到 UTF-8 多字节字符(如中文、emoji)时,若没加u修饰符,会按字节拆分,结果错乱 -
/\w+/这类模式根本不会匹配空格或标点,结果远小于真实长度 - 正则引擎要编译、回溯、捕获,比直接查长度慢一个数量级以上
正确做法:用内置函数,不是正则
PHP 有明确分工:
- ASCII 场景(纯英文、数字、符号)→ 用
strlen - UTF-8 多语言场景(含中文、日文、emoji)→ 必须用
mb_strlen($str, 'UTF-8') - 不确定编码?先
mb_detect_encoding判断,再传对应编码,别硬套UTF-8
示例对比:
立即学习“PHP免费学习笔记(深入)”;
$str = "你好a?"; echo strlen($str); // 输出 10(字节长度,不可信) echo mb_strlen($str, 'UTF-8'); // 输出 4(正确字符数)
真要用正则的唯一合理场景:统计某类字符出现次数
如果你实际想问的是“字符串里有多少个数字”或“有几个中文字符”,那才是 preg_match_all 的正当用途:
- 数字个数:
preg_match_all('/\d/', $str, $matches)→ 返回匹配次数 - 中文字符个数:
preg_match_all('/[\x{4e00}-\x{9fff}]/u', $str, $matches) - 注意:必须加
u修饰符,否则 Unicode 范围无效
把“长度”和“匹配次数”混为一谈,是初学正则时最常踩的逻辑坑——函数名里的 _all 指的是「所有匹配结果」,不是「所有字符」。











