零宽空格

显示宽度为零的不可见字符 (U+200B)。用作换行提示和文本处理控制。

零宽空格 (Zero-Width Space, U+200B) 是一种显示宽度为零的不可见字符。屏幕上不会显示任何内容,但它确实存在于文本数据中,并被计为一个字符。它主要作为可换行位置的提示,浏览器允许在该字符位置进行换行。在 Unicode 的"通用类别"中,它被归类为格式字符 (Cf)。

零宽空格在几个实际场景中很重要。在泰语和高棉语等不在词与词之间使用空格的语言中,零宽空格标记词边界并实现适当位置的换行。在 Web 开发中,在不含空格的长字符串 (如 URL 或哈希值) 中插入零宽空格,可以在不破坏布局的情况下实现换行。在 HTML 中可以用 ​ 或 ​ 插入。

相关的不可见字符还有零宽非连接符 (U+200C, ZWNJ),用于防止连接,在波斯语和印地语书写中使用;零宽连接符 (U+200D, ZWJ),用于促进字符连接,在表情符号的 ZWJ 序列 (如家庭表情符号) 中使用。这些不可见字符都具有零显示宽度,但在文本处理中各有不同的含义。

从安全角度来看,零宽空格可能被用于指纹追踪 (在文本中嵌入不可见标识符的技术)。这种手法在机密文档中嵌入零宽字符的模式,用来识别泄露来源。另一方面,"在域名中混入零宽字符来伪装成合法域名"这类说明需要注意。零宽空格这类不可见的字符按 IDNA 规则不能用于域名 (U+200B 被禁止使用),主要浏览器一侧也会将其拦下。实际需要警惕的,是把它混进显示在屏幕上的链接字符串、邮件正文或表单的输入值里,让基于简单字符串一致的检查被绕过的用法。输入值的清洗应把去除零宽字符也考虑进来。

常见的问题是复制粘贴时无意中混入零宽空格。从网页复制来的文本里含有零宽空格时,会出现外观相同却字符串比较失败、搜索无法命中、密码通不过之类的问题。麻烦之处在于,一般的空白去除并不能把它消掉。零宽空格在 Unicode 的分类上属于格式字符,因此不匹配正则表达式的 \s,用 JavaScript 的 trim() 或 Python 的 strip() 也会留下来 (以 Node.js 26 / Python 3 实测)。要去除时,请像 \u200B 到 \u200D 与 \uFEFF 这样,明确指定对象的码点。由于是用眼睛找不出来的字符,在字符串比较对不上却看不出差别的时点就怀疑这一可能,才是捷径。

在字符计数方面,零宽空格虽然不显示却被计为一个字符,成为可见字符数与实际字符数产生差异的原因。例如在"你好"的字与字之间插入了 3 个零宽空格时,看起来是 2 个字符但实际是 5 个字符。在提交方以机械方式清点字数的场合,这一差额会被直接当作超出或不足来处理。把从 Web 复制来的稿件贴进有字数限制的栏目时,先落成纯文本、把不可见字符去掉之后再来计数,就能防止返工重写。

分享这篇文章