返回

隐藏字符检查

文本处理

正在载入

正在加载工具

工具代码会在打开时按需载入,请稍候。

本工具的全部运算都发生在你的浏览器中,输入内容不会发送到任何服务器。

关于这个工具

看起来相同的文本可能包含不同的码点。粘贴文本或打开本地 UTF-8 文件,可定位零宽字符、不换行空格、方向控制符和异常 UTF-16 单元。检查器使用固定 Unicode 17.0.0 数据,以纯 ASCII 转义显示证据,避免诊断文本被双向控制符重新排序。所有结果默认不选中。请根据用途决定删除哪些具体出现位置;原文保留,发现某个字符并不代表文本恶意。

常见用途

  • 定位标识符、搜索词或复制值中导致精确比较失败的不换行空格或零宽空格。
  • 检查复制的源文本中意外的方向控制符和分隔符,不执行文本,也不在诊断报告中直接呈现这些控制符。
  • 在删除前区分正常表情连接符、文字塑形连接符、变体选择符与意外的复制粘贴残留。

使用方法

  1. 1.粘贴文本或打开一个严格 UTF-8 解码的文本文件。先检查原始输入,再决定删除项。直接输入 \u200B 这样的拼写只会得到普通 ASCII 字符;下方示例使用转义 JSON 字符串,仅用于准确展示测试数据。 运行检查,查看码点、Unicode 名称或诊断标签、类别和准确位置。每页显示 50 行,计数和 JSON 报告仍覆盖所有出现位置。原文与清理后文本的转义预览各最多覆盖 4,000 个输入 UTF-16 单元。
  2. 2.按原始 UTF-16 偏移逐行选择。没有默认删除项,选择一次出现不会自动选择所有同类字符。仅移除选中的完整单元或码点,其余空格、换行和原始文本全部保留。
  3. 3.核对清理后的转义预览和剩余结果,再下载完整纯 ASCII JSON 诊断报告。复制或下载原始清理文本前需明确确认已检查;只要仍有未配对代理项,这两项操作就不可用。修改输入会使旧检查和选择失效。

可精确复现的字符检查

保留 NBSP,仅移除零宽空格

input (ASCII JSON): "A\u00A0B\u200BC"
selected UTF-16 offsets: [3]
{"codePointCount":5,"occurrences":[{"codePoint":"U+00A0","utf16Offset":1,"codePointIndex":1,"line":1,"column":2},{"codePoint":"U+200B","utf16Offset":3,"codePointIndex":3,"line":1,"column":4}],"cleanedAscii":"\"A\\u00A0BC\"","rawExportable":true}

仅选中偏移 3。偏移 1 的 NBSP 仍保留,因此清理结果不是由普通 ASCII 空格组成的 A BC。

相同字符仅删除第一次出现

input (ASCII JSON): "x\u200B\u200By"
selected UTF-16 offsets: [1]
{"codePointCount":4,"occurrences":[{"codePoint":"U+200B","utf16Offset":1,"codePointIndex":1,"line":1,"column":2},{"codePoint":"U+200B","utf16Offset":2,"codePointIndex":2,"line":1,"column":3}],"cleanedAscii":"\"x\\u200By\"","rawExportable":true}

连续两个 U+200B 产生两行。选择偏移 1 后,原本位于偏移 2 的字符保持不变。

检查并明确删除方向控制符

input (ASCII JSON): "a\u202Eb\u202Cc"
selected UTF-16 offsets: [1,3]
{"codePointCount":5,"occurrences":[{"codePoint":"U+202E","utf16Offset":1,"codePointIndex":1,"line":1,"column":2},{"codePoint":"U+202C","utf16Offset":3,"codePointIndex":3,"line":1,"column":4}],"cleanedAscii":"\"abc\"","rawExportable":true}

原文含有 RIGHT-TO-LEFT OVERRIDE 和 POP DIRECTIONAL FORMATTING。两个选中的控制符被移除,字母仍按原始逻辑顺序保留。

保留表情连接符和变体选择符

input (ASCII JSON): "\uD83D\uDC69\u200D\uD83D\uDCBB\u0645\u06CC\u200C\u0631\u0648\u0645\u2764\uFE0F"
selected UTF-16 offsets: []
{"codePointCount":11,"occurrences":[{"codePoint":"U+200D","utf16Offset":2,"codePointIndex":1,"line":1,"column":2},{"codePoint":"U+200C","utf16Offset":7,"codePointIndex":5,"line":1,"column":6},{"codePoint":"U+FE0F","utf16Offset":12,"codePointIndex":10,"line":1,"column":11}],"cleanedAscii":"\"\\uD83D\\uDC69\\u200D\\uD83D\\uDCBB\\u0645\\u06CC\\u200C\\u0631\\u0648\\u0645\\u2764\\uFE0F\"","rawExportable":true}

女性程序员表情使用 ZWJ,波斯语词汇使用 ZWNJ,爱心使用 VS16。补充平面表情各占两个 UTF-16 单元。三个格式字符都被列出但保持未选中,保留这些有意使用的序列。

删除空格和制表符,保留 CRLF

input (ASCII JSON): "a b\tc\r\nd"
selected UTF-16 offsets: [1,3]
{"codePointCount":8,"occurrences":[{"codePoint":"U+0020","utf16Offset":1,"codePointIndex":1,"line":1,"column":2},{"codePoint":"U+0009","utf16Offset":3,"codePointIndex":3,"line":1,"column":4},{"codePoint":"U+000D","utf16Offset":5,"codePointIndex":5,"line":1,"column":6},{"codePoint":"U+000A","utf16Offset":6,"codePointIndex":6,"line":1,"column":7}],"cleanedAscii":"\"abc\\r\\nd\"","rawExportable":true}

选中 SPACE 和 TAB。CR、LF 编码为 UTF-8 后按原字节保留;它们的原始位置同属第 1 行,分别是第 6、7 列。

区分 CRLF、行分隔符和段落分隔符

input (ASCII JSON): "A\r\nB\u2028C\u2029D"
selected UTF-16 offsets: [4]
{"codePointCount":8,"occurrences":[{"codePoint":"U+000D","utf16Offset":1,"codePointIndex":1,"line":1,"column":2},{"codePoint":"U+000A","utf16Offset":2,"codePointIndex":2,"line":1,"column":3},{"codePoint":"U+2028","utf16Offset":4,"codePointIndex":4,"line":2,"column":2},{"codePoint":"U+2029","utf16Offset":6,"codePointIndex":6,"line":3,"column":2}],"cleanedAscii":"\"A\\r\\nBC\\u2029D\"","rawExportable":true}

原始行位置把 CRLF 计为一次换行,每个 Unicode 分隔符也各计一次。删除 U+2028 会连接 B 和 C,保留的 U+2029 仍分隔后一个段落。

保留分解与合成拼写的区别

input (ASCII JSON): "e\u0301\u00E9"
selected UTF-16 offsets: []
{"codePointCount":3,"occurrences":[],"cleanedAscii":"\"e\\u0301\\u00E9\"","rawExportable":true}

组合锐音符 U+0301 不在此检测范围内,也没有选中任何字符。e 加附加符号与预合成 U+00E9 保持不同,不做规范化。

仍有一个未配对代理项时阻止原始导出

input (ASCII JSON): "A\uD800B\uDC00C"
selected UTF-16 offsets: [1]
{"codePointCount":5,"occurrences":[{"codePoint":"U+D800","utf16Offset":1,"codePointIndex":1,"line":1,"column":2},{"codePoint":"U+DC00","utf16Offset":3,"codePointIndex":3,"line":1,"column":4}],"cleanedAscii":"\"AB\\uDC00C\"","rawExportable":false}

删除了高代理项,但低代理项仍未配对。转义诊断输出可用,原始复制和 UTF-8 下载仍被阻止。

明确删除两个异常单元

input (ASCII JSON): "A\uD800B\uDC00C"
selected UTF-16 offsets: [1,3]
{"codePointCount":5,"occurrences":[{"codePoint":"U+D800","utf16Offset":1,"codePointIndex":1,"line":1,"column":2},{"codePoint":"U+DC00","utf16Offset":3,"codePointIndex":3,"line":1,"column":4}],"cleanedAscii":"\"ABC\"","rawExportable":true}

两个未配对代理项都被选中,输出恰为 ABC;通过单独的检查确认后可进行原始导出。

删除 BOM,保留补充平面变体选择符

input (ASCII JSON): "\uFEFF\uD83D\uDE00\uDB40\uDD00X"
selected UTF-16 offsets: [0]
{"codePointCount":4,"occurrences":[{"codePoint":"U+FEFF","utf16Offset":0,"codePointIndex":0,"line":1,"column":1},{"codePoint":"U+E0100","utf16Offset":3,"codePointIndex":2,"line":1,"column":3}],"cleanedAscii":"\"\\uD83D\\uDE00\\uDB40\\uDD00X\"","rawExportable":true}

选中 U+FEFF,保留表情与 U+E0100。选择符起于 UTF-16 偏移 3、码点索引 2,说明这两种坐标为何不同。

常见检查误区

  • 因为出现在表格中就删除全部结果,包括有意保留的空格、换行、连接符和变体选择符。
  • 把 UTF-16 偏移当成字节偏移或屏幕列;表情和组合序列会让这些度量不同。
  • 粘贴六个 ASCII 字符 \u200B,却期待工具自动解码为真正的零宽空格。
  • 把每页 50 行或 4,000 单元的截短预览误认为报告与计数不完整。
  • 把转义报告当成已经清除秘密的内容;ASCII 转义以可读、可逆形式保留内容。
  • 期待删除操作顺便规范化等价拼写或转换换行;只有明确选中的出现位置会变化。

限制与说明

  • 检测范围为 Unicode 17.0.0 通用类别 Cc、Cf、Zs、Zl、Zp,Default_Ignorable_Code_Point 属性,以及未配对 UTF-16 代理项。因此普通 U+0020 SPACE、制表符和换行也会列出。属性重叠只产生一个出现项,不会重复计数。本工具不穷尽所有视觉不可见字形、混淆字母、恶意代码或不安全标识符;字体和应用可能以不同方式显示同一文本。 零宽连接符 ZWJ、零宽非连接符 ZWNJ、变体选择符和双向控制符在表情、书写系统和混合方向文本中都有合法用途。删除可能改变拼写、塑形、表情呈现或阅读顺序。一般组合附加符号并非全部检测项。本工具不提供安全判定、字素簇分段或 Unicode 双向算法的显示预览。
  • UTF-16 偏移与码点索引从 0 开始;行和列从 1 开始,列按码点而非字素簇、终端单元格或像素宽度计数。补充平面字符占两个 UTF-16 单元但只算一个码点。未配对代理项按一个诊断伪单元计数,不属于 Unicode 标量值。CRLF 只算一次换行,CR 和 LF 自身位于旧行的连续两列。 LF、单独 CR、VT、FF、NEL、LS、PS 各自在之后开始新行;制表符只占一个码点列,空输入计为一行。
  • 检查器不做 Unicode 规范化、首尾修剪、空白替换或隐式换行转换。删除以原始偏移为准,保留每个未选中的 UTF-16 单元,且原文仍可查看。浏览器的粘贴或剪贴板处理可能在本工具之外改变文本;需要精确换行时,优先使用严格文件输入并检查下载结果。
  • 处理同步且在本地完成:输入最多 100,000 个 UTF-16 单元,UTF-8 文件最多 400,000 字节;无上传、网络查询或持久化。不合法 UTF-8 文件会被拒绝,不会用 U+FFFD 替代。存在的 BOM 会作为 U+FEFF 检查,不会静默去除。其他解码器已经改变的文本无法还原。 纯 ASCII JSON 报告上限为 40,000,000 个字符,超过上限会停止导出,不返回部分报告。
  • 预览和诊断 JSON 会转义非 ASCII 字符与控制符;原始清理输出刻意保留其余原字符,仍可能影响其他编辑器的显示。完整报告可能包含完整的转义原文和清理文本,转义不是脱敏或加密。分享前需检查隐私内容。仍有未配对代理项时禁止原始 UTF-8 导出,避免编码时静默替换。 Unicode 安全指导的范围远超字符属性检测。UTR #36 是已稳定化的历史报告,并非当前完整检查清单;Unicode 引导读者参考 UTS #39 等较新资料。本工具没有实现这些文档中的完整安全机制,不能证明字符串、文件或仓库安全。

常见问题

为什么普通空格和换行也会列出?

声明的范围包括所有 Cc 控制符及 Zs/Zl/Zp 分隔符,因此包含 U+0020、TAB、CR 和 LF。列出是为了完整检查属性,不代表建议删除。请不要选中有意保留的空白。

检测结果或没有结果,能否判断文本安全?

不是。零宽连接符可组成表情序列,非连接符可影响词语塑形,变体选择符可指定呈现方式。选择删除前,请核对上下文与文本用途。 不能。报告仅覆盖这里声明的固定 Unicode 属性与异常 UTF-16。它不检测所有易混淆字符、异常组合序列、依赖字体的空白字形或有害程序行为。安全判断还需要理解语言的工具和人工审核。

相同字符重复出现时,可以只删除一个吗?

可以。选择以每次出现的原始 UTF-16 偏移为准。对于 x\u200B\u200By,选择偏移 1 只删除第一个零宽空格,原本位于偏移 2 的字符仍保留。输出从原文重建,前面的删除不会导致后面的选择错位。

为什么有时不能复制或下载原始清理文本?

未配对代理项没有合法的 UTF-8 编码。如果清理后仍存在这样的单元,原始导出会被阻止,而不会静默替换成 U+FFFD。仍可查看纯 ASCII 诊断报告;只有确定适合修改时,才删除对应异常单元。

相关工具