Unicode归一化与不可见字符清理

本地处理
  • 打赏支持
  • 分享链接
  • 反馈建议
把文本粘进来,下方列出所有不可见或可疑字符的位置与码点。零宽字符在编辑器和网页上都看不见,但会让等号比较失败、让排版莫名错位,从网页复制代码或从聊天工具复制文本时最容易带上它们。
处理结果
归一化形式的区别
形式做什么典型场景
NFC把分解序列合成单字符,例如字母加声调合成带调字母存储与显示的标准形式,网页与数据库建议统一用 NFC
NFD把带调字符分解为基础字符加组合符号需要逐字符分析、排序或去除声调时使用
NFKC在 NFC 基础上再做兼容映射,全角字母数字转半角、上标变普通数字搜索、去重与比较前的规范化处理
NFKD在 NFD 基础上再做兼容映射需要最大程度抹平写法差异的检索场景
说明:本工具与站内的文字隐藏工具用途相反——那个工具用来插入零宽字符实现隐藏,本工具用来检测并清除它们。单纯的符号宽度转换请使用全角半角互转工具。

工具说明

同一个字符在 Unicode 里可能有多种表示方式,另外还有很多渲染为空白但占据码位的字符。本工具扫描文本中每个码点,把可疑的挑出来,并按你选择的方式处理。

常见的隐形麻烦制造者

  • 零宽空格与零宽连接符:不占宽度也不显示,常被复制自网页或即时通讯,会导致字符串比较不相等、正则匹配失败。
  • 字节顺序标记:文件开头的一个不可见字符,带在文本里会让解析器把第一个字段名读错。
  • 不换行空格:看起来与普通空格一样,但不会被当作分隔符,拆分字符串时会失效。
  • 方向控制符:控制文字排列方向,混在普通文本里会造成显示顺序错乱。
  • 软连字符:只在换行时可见,复制进代码会引发难以排查的语法错误。

为什么要做归一化

带声调的拉丁字母、韩文音节、部分中日汉字都有合成与分解两种写法。它们在视觉上完全一样,但码点序列不同,因此直接比较会判为不相等。统一归一化形式之后,同样的文字才能稳定地做比较、去重与检索。

处理方式怎么选

  • 只检测:先看清楚有哪些问题,再决定怎么处理,适合排查阶段。
  • 清理不可见字符:移除零宽字符、方向控制符与控制字符,保留正常空白。
  • 替换特殊空白:在上一步基础上,把不换行空格与全角空格统一成普通空格。
  • 折叠连续空白:进一步把连续空格合并成一个、连续空行合并成一行,适合清理从网页复制的正文。

你可能还想问

为什么复制来的代码总是报错?

最常见的原因是带上了不可见的零宽字符。它们不影响视觉,但会被当成有效字符参与语法解析,于是变量名看起来一样却无法匹配,或者字符串比较结果与预期不符。把代码粘进本工具检测一遍,再复制处理结果,通常就能解决。

NFC 和 NFD 该选哪个?

存储与展示统一选 NFC,它是网页与大多数数据库的推荐形式,字符数也更短。只有在需要逐字符处理时才用 NFD,例如去除声调、按基础字母排序或统计字符个数。两种形式互相转换不会丢失信息,可以随时来回切换。

NFKC 为什么会改变我输入的内容?

因为它在合成的基础上还做兼容映射,会把全角字母数字转成半角、把上标数字转成普通数字、把连字拆开。这对搜索与去重是好事,能抹平写法差异,但它确实会改变原文的视觉形态。如果只是要清理隐藏字符,选择 NFC 或不做归一化更安全。

全角空格和不换行空格有什么区别?

全角空格宽度等于一个汉字,常见于中文排版中用于对齐,码点是 3000。不换行空格宽度与普通空格相同,但禁止在其处换行,码点是 00A0。两者都不是普通空格,参与字符串拆分与比较时行为不同,需要统一时选第三个处理方式。