不可见字符

存在于文本数据中但不在屏幕上显示的字符的统称。包括零宽空格、双向控制字符、软连字符等,会影响字符计数结果。

不可见字符 (invisible character) 是指存在于文本中却没有视觉表现的字符的统称。与控制字符 (换行、制表符等) 不同,不可见字符大多作为"看不见的指令"影响文本的显示和处理方式。在字符计数中,不可见字符是最容易造成困扰的陷阱之一。

Unicode 定义了大量不可见字符。零宽空格 (U+200B) 是没有宽度的空白,插入在长单词中间可以标记允许换行的位置。零宽连接符 (ZWJ,U+200D) 用于连接前后字符,在 emoji 合成中发挥关键作用 (👨+ZWJ+👩+ZWJ+👧 = 👨‍👩‍👧)。零宽非连接符 (ZWNJ,U+200C) 则相反,用于阻止字符连接,在阿拉伯语和波斯语中控制字母的连写形式。

双向控制字符也属于不可见字符。左至右标记 (LRM,U+200E) 和右至左标记 (RLM,U+200F) 用于在阿拉伯语、希伯来语与英语混排的文本中控制书写方向。这些字符虽然看不见,但对文本的显示顺序有重大影响。

不可见字符对字符计数的影响不容忽视。从网页复制粘贴文本时,零宽空格或双向控制字符可能会混入其中。看起来完全相同的文本,字符计数器却返回不同的数值 - 遇到这种情况就应该怀疑是否混入了不可见字符。例如"Hello"被计为 7 个字符而非 5 个,可能是"H"和"e"之间插入了 2 个零宽空格。

从安全角度看,不可见字符可能被用于恶意攻击。2021 年曝光的"特洛伊源码"攻击,通过在源代码中插入双向控制字符,使代码在显示上看起来正常,实际执行的却是不同的逻辑。在用户名或密码中插入零宽字符,可以创建看起来相同但实际不同的字符串,这种手法也已被发现。

应对不可见字符的措施是在文本处理前进行净化 (sanitize),即去除不必要的不可见字符。正则表达式 /[\u200B-\u200F\u2028-\u202F\u2060-\u206F\uFEFF]/g 可以检测并去除主要的不可见字符。但需要注意,ZWJ 是 emoji 合成所必需的,一律去除会导致 emoji 被拆散。因此需要根据具体用途进行选择性去除。

分享这篇文章