不可见字符不一定是“空字符”。它可以标记词语边界、阻止换行、连接字母形状、选择显示样式,甚至改变文字在屏幕上的排列方向。
两个看起来完全相同的字符串,内部可能携带不同指令。
“空格”其实包含很多不同工作
U+0020 SPACE 是键盘上最熟悉的空格。Unicode 中还有其他具有间距的字符:
- U+00A0 NO-BREAK SPACE 有可见宽度,但不鼓励在这里换行;
- U+2009 THIN SPACE 提供更窄的排版间隔;
- U+3000 IDEOGRAPHIC SPACE 占据一个东亚全角字格;
- U+2800 BRAILLE PATTERN BLANK 是没有凸点的盲文字符,并不是通用空格。
它们看起来都可能是一片空白,但宽度、换行行为、语义和无障碍表现并不相同。仅仅因为平台拒绝一种空格,就用另一种“看起来空白”的字符替代,很容易产生意外布局。
零宽字符仍然可以携带指令
一些格式字符通常不绘制可见字形:
- U+200B ZERO WIDTH SPACE 提供一个没有可见间隔的可换行位置;
- U+2060 WORD JOINER 不增加宽度,同时阻止在这里断开;
- U+200C ZERO WIDTH NON-JOINER 可以阻止连写或合字;
- U+200D ZERO WIDTH JOINER 可以鼓励连接,也是 Emoji 组合序列中的连接方式;
- U+FE0E/U+FE0F 变体选择符请求文字或 Emoji 显示。
把它们全部叫作“隐形空格”,会掩盖各自完全不同的任务,其中几个根本不是空格。
在需要上下文塑形的文字系统中,连接符和非连接符可以参与正确拼写或排版。无差别删除它们,有可能改变单词形态甚至含义。
方向控制符解决的是真实多语言问题
阿拉伯文和希伯来文主要从右向左排列,拉丁字母与数字通常从左向右排列。Unicode 双向算法负责决定混合文字怎样显示,方向标记、隔离符、嵌入与覆盖控制则帮助软件处理歧义。
这些字符是多语言文字的重要基础设施。但逻辑存储顺序和视觉显示顺序可以不同,如果软件处理不当,控制符也可能让屏幕内容看起来与程序实际处理的序列不一致。
正因如此,代码编辑器和安全工具会特别关注不成对或异常出现的双向控制符。
为什么复制来的文字特别难排查?
不可见字符常见来源包括:
- 从格式化文档或网页复制;
- 输入法与语言塑形;
- 自动换行;
- Emoji 组合序列;
- 刻意制作空白昵称或特殊布局。
表现出来的症状可能是搜不到内容、出现两个看似重复的用户名、网址比较结果不同、意外换行,或者光标像被某个位置“卡住”。
正确的排查方式是查看代码点,而不是不停按退格键碰运气。
隐藏字符和相似字符也涉及安全
Unicode 支持世界各地的文字系统,因此不同字符可能具有相似字形。拉丁字母 a 和西里尔字母 а 不是同一个字符,即使某种字体把它们画得几乎一样。
Unicode 技术标准 #39 定义了检测易混淆标识符的机制。它的目标是发现风险,而不是把所有文字粗暴压成 ASCII。语境非常重要:国际化姓名中混合文字可能完全合理,同样的混合方式如果出现在仿冒银行域名中就值得警惕。
有关“不可感知 NLP 攻击”的研究还发现,不可见插入、同形字符替换、字符重排和删除控制,可以在视觉几乎不变的情况下改变搜索及语言处理系统的输出。
所以提供隐藏字符的工具,也应该解释合理用途与风险。
哪些用途安全,哪些用途风险较高?
合理用途包括测试文字渲染、分析文档、处理换行,以及在确实需要的文字系统中使用连接控制。
高风险用途包括:
- 伪装链接或账号名称;
- 绕过审核或重复检测;
- 在源代码中插入控制符;
- 在平台明确禁止时制造空白身份;
- 对读者隐藏内容,却仍让软件处理它。
即使只是无害装饰,如果屏幕阅读器反复朗读“空白”或陌生字符名称,也会降低无障碍体验。
产品应该怎样处理?
接受公开账号标识的应用可以考虑:
- 对异常格式控制符显示可见警告;
- 在适合的场景比较正规化形式和 confusable skeleton;
- 保留合法多语言文字,不要删除大片 Unicode 区段;
- 在诊断工具中显示代码点;
- 根据标识符用途设计允许字符范围;
- 把展示昵称与安全敏感的账号 ID 分开。
正规化、易混淆检测和删除格式控制,解决的是三种不同问题。不存在一个适合所有语言和场景的“清理 Unicode”按钮。
看不见不等于没有意义;没有字形,本身也可能是一条指令。
空白字符工具会标出每个字符及其预期行为。请把它用于测试和正当排版需求,而不是伪装文字或规避平台规则。