应使用正则/[\x{200b}-\x{200d}\x{feff}\x{2028}\x{2029}]/u检测,需加/u修饰符,覆盖零宽空格、非连接符、连接符、bom及分隔符等常见干扰字符。

用正则快速检测字符串是否含零宽字符
零宽空格(U+200B)这类字符肉眼不可见,但会干扰 strlen()、mb_strlen()、关键词匹配甚至 JSON 解析。最直接的检测方式是正则探测:preg_match('/[\x{200B}-\x{200D}\x{FEFF}\x{2028}\x{2029}]/u', $str) 返回 1 就说明存在。
常见误判点:
- 没加
/u修饰符 → UTF-8 多字节字符无法匹配,永远返回 0 - 只查
\x{200B}单个码点 → 漏掉U+200C(ZWNJ)、U+200D(ZWJ)、U+FEFF(BOM)等同样危险的控制符 - 在数据库字段里查不到?可能已被 MySQL 自动截断或转换,建议先用
HEX(content)查原始字节
PHP7.0 中安全清除零宽字符的写法
PHP 7.0 原生支持 Unicode 正则(需 PCRE 8.32+),推荐用 preg_replace() 一次性清除主流干扰字符。注意不能只清 \u200b,要覆盖完整集合:
$clean = preg_replace('/[\x{200B}-\x{200D}\x{FEFF}\x{2028}\x{2029}]/u', '', $str);
这个表达式涵盖:
-
\x{200B}–\x{200D}:零宽空格、零宽非连接符、零宽连接符 -
\x{FEFF}:UTF-8 BOM(常出现在文件开头,但也会被粘贴进表单) -
\x{2028}、\x{2029}:行分隔符和段落分隔符,json_encode()会报错
别用 str_replace() 逐个替换——它不支持 Unicode 码点,str_replace("\u200b", "", $str) 实际上什么也没删。
用户输入、JSON 解析、日志入库前必须过滤
零宽字符不是“偶尔出现”,而是安卓输入法、微信粘贴、爬虫注入的高频载体。以下三类场景不清理必出问题:
- 用户提交昵称/搜索词 →
mb_strlen($input, 'UTF-8')显示长度异常,影响前端截断或后端敏感词匹配 - 调用
json_encode($data)→ 遇到\x{2028}直接返回false,且无明确错误提示 - 写入 MySQL TEXT 字段 → 若字段为
utf8mb4可存,但某些旧版客户端或 ORM 会静默截断
建议在框架入口(如 Laravel 的中间件、ThinkPHP 的公共函数)统一调用一次过滤,而不是每个 $_POST 字段单独处理。
为什么 trim() 对零宽空格完全无效
trim() 默认只识别 ASCII 控制符(空格、\t、\n 等),对任何 Unicode 控制字符都无感。哪怕你显式传参:trim($str, "\u{200B}"),PHP 7.0 也不支持这种语法(u{...} 是 PHP 7.4+ 特性)。
所以别指望 trim() 能救场。更麻烦的是:trim($str) === '' 可能为 false,但实际内容全是零宽字符——这时 strlen($str) 不为 0,mb_strlen($str, 'UTF-8') 却显示“有字符”,但 echo 出来一片空白。
真正要判断“视觉上为空”,得先清除再判空:preg_replace('/[\x{200B}-\x{200D}\x{FEFF}\x{2028}\x{2029}]/u', '', $str) === ''。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











