从表格里导出一份名单、从聊天记录里抠一批关键词,接下来通常要做同一件事:去掉重复、去掉空行、排个序。看着简单,但顺序做反或者少做一步,结果就是「明明肉眼能看到两行一样,工具却说没有重复」。
这篇讲清楚正确的处理顺序,以及那些看不见的字符从哪来。全部操作可以在文本统计与去重排序里叠加完成。
一、正确顺序:先规范化,再去重,最后排序
固定按这个顺序走:
- 去首尾空格(每行的行首行尾)
- 压缩连续空格(行内多个空格并成一个)
- 删空行
- 整行去重
- 排序
- 加序号(如果需要)
关键在于 1、2 必须在 4 之前。整行去重的判断依据是「两行字符串完全相同」,张三 和 张三 (末尾一个空格)在机器看来是两个不同的值。先规范化再去重,这一步能解决大多数「去不掉」的情况。
排序放在去重之后,因为对更少的行排序更快,而且排完再去重会打乱你可能需要保留的原始顺序信息。
加序号一定放最后。先加序号再去重,每行都带上了不同的编号,就永远不会有重复行了——这个错误犯过一次就不会忘。
二、看起来一样却去不掉的四种原因
行尾隐藏空格或制表符。从网页表格、PDF、Excel 复制时最常见。执行「去首尾空格」即可。
换行符不一致。Windows 是 \r\n,Mac 和 Linux 是 \n。混合来源的文本里,一部分行末尾多一个不可见的 \r,导致同名两行判定为不同。多数工具会统一处理,但如果你在自己的脚本里比较,需要先规范化换行。
全角与半角。全角空格 \u3000、全角括号、全角数字都是不同的码点,ABC 和 ABC 是两个字符串。中文输入法下敲出的标点常常是全角。用中英文智能排版可以做全半角统一,再回来去重。
零宽字符与 BOM。零宽空格 \u200b、零宽连接符 \u200d、字节序标记 \ufeff 都是完全不可见的。它们来自网页复制(有些站点故意插入零宽字符做防爬或水印)、微信复制、以及记事本另存的 UTF-8 文件。特征是「肉眼完全相同、长度统计却不一样」——所以怀疑有隐形字符时,先看字符数统计对不对得上。
三、大小写要不要算不同
工具通常按「完全相同」去重,也就是区分大小写。而这个默认值是否符合预期,取决于数据是什么:
- 邮箱:域名部分不区分大小写,实践中整体也按不区分处理。
Tom@QQ.com和tom@qq.com应视为同一个,去重前先统一转小写。 - 人名、中文内容:不涉及。
- 密码、Token、Base64、哈希值:绝对区分大小写,转换会直接破坏数据。
- URL:域名不区分,路径区分(服务器配置决定)。粗暴转小写可能导致链接失效。
结论是:转小写是个有损操作,只在你确认该字段语义上不区分大小写时才做。
四、带结构的数据不要按行处理
如果你的内容其实是表格(每行是逗号分隔的多列),按行去重会有两个问题:
- 只要有一列不同,整行就算不重复。而你真正想要的往往是「按手机号去重,保留第一条」——这是按列去重,不是按行去重。
- CSV 的字段里允许出现逗号和换行(用引号包裹),按行切分会把一条记录拆成两行,数据直接错位。
这类内容应该用表格格式互转先解析成结构化数据,再按指定列处理。判断依据很简单:内容里有分隔符和引号,就当表格处理,不要当纯文本。
五、顺手能确认的几件事
字数是否达标。统计工具会同时给出总字符数、不含空格字符数、汉字数、英文单词数。投稿和公众号的「字数」口径不同——公众号按字符计(含标点),Word 的「字数」中文按字算、英文按词算,同一篇文章两个口径能差出百分之十几。核对稿件字数要先问清对方按哪个口径。
高频词有哪些。词频统计可以快速看出一批关键词里的集中度,做 SEO 关键词整理、用户反馈归类时比逐条看快得多。
两份名单差在哪。如果你有「上次的名单」和「这次的名单」,要找出新增和减少的人,用去重解决不了,应该用文本比较工具做行级对比,它会直接标出哪几行是新增、哪几行被删除。
常见问题
去重会保留第一次出现的那行还是最后一行? 保留第一次出现的,后续重复的删除,剩余行的相对顺序不变。所以如果原始顺序有意义(比如按时间排列),去重不会破坏它。
能只删连续的重复行吗?
那是另一种语义(类似命令行的 uniq),需要先排序才能起到全局去重效果。整行去重是全文范围的,不要求相邻。
几万行会卡吗? 纯文本处理在浏览器里很快,几万到十几万行一般在一两秒内完成。真正卡的是渲染,超大文本建议分批处理。
处理完的顺序乱了怎么恢复? 恢复不了。建议在做排序这类破坏性操作前,先把原始文本另存一份。
数据会上传吗? 不会。统计、去重、排序、排版全部在浏览器本地完成,客户名单、手机号这类内容不会离开你的设备。涉及个人信息的名单,这一点比处理速度重要。