名单去重了还有重复?批量数据清理的五个坑

2026-11-05约 8 分钟文本处理涉及 5 个工具

从 Excel、日志、聊天记录里粘出来的名单,肉眼看着干净,去重时总有残留。原因几乎都在「看不见的差异」上 —— 判重规则、字符形态、以及排序的码位比较。

核心要点
  • 判重的单位是整行,两行去掉首尾空白后完全相同才算重复,不做相似度判断,也不忽略标点或词序
  • 去重的比较与输出都会先 trim,所以粘带缩进的内容会丢结构,代码、YAML 这类文本不适合用它整理
  • 普通排序按 UTF-16 码位比较,大写字母排在小写字母前面,所以 Apple 会跑到 apple 前面
  • 自然排序把每行切成数字段与非数字段交替比对,item2 因此排在 item10 前面,而普通排序正好相反
  • 中文排序既不按拼音也不按笔画,而是按 Unicode 码位,要拼音序得先把文本转成拼音再排

#先分清是哪一种「重复」

「去了重还有重复」其实分两种情况:一是判重规则没覆盖到那些差异,二是重复根本不在同一行里。 混在一起处理,改哪个工具都不对。

判据很简单:把两条疑似重复的行复制出来,逐字符对比。

现象真正的原因怎么处理
两条看着一样却都保留尾部空格、全角字符、大小写不同先 trim 与全角统一,再判重
同一个人出现两次但写法不同信息不在同一行(如「张三 138…」与「张三」)需要按字段拆分,工具做不到
去重后行数没变每行都不同(时间戳、序号导致)先去掉无关列再判重
空行也被算进去了去空白行没勾确认「去空白行」是勾选状态

#整行判重:什么算重复

判重的单位是整行:两行去掉首尾空白后完全相同才算重复。 它不做相似度、不忽略标点、不忽略词序 —— 「苹果 香蕉」和「苹果香蕉」是两条不同的行。

用 文本去重 时,三个行为决定了结果:

  • 比较和输出都会先 trim,行首行尾的空格被去掉
  • 顺序按首次出现固定,不会重排成字母序
  • 勾选忽略大小写后,输出保留第一次出现时的大小写:Apple 在前就输出 Apple,apple 在前就输出 apple

也就是说,它的输出是一条「首次出现顺序 + 原始大小写」的干净列表。想按字母或数字排,接着用排序工具。

注意

「去空白行」默认是勾选的,所以粘进来的首尾空行会直接被吃掉。粘贴带缩进的内容(代码、Markdown 列表、YAML)时更要小心 —— 缩进会被 trim 掉,结构跟着就变了。这类文本不要用去重工具整理。

#去重会动你的缩进

trim 是去重的必要步骤(否则尾部空格会造成假重复),代价是缩进信息丢失。 这个取舍对名单类数据完全正确,对代码类数据完全错误。

判断标准:这段文本的缩进有语义吗?

  • 名单、标签、ID、URL 列表:缩进无语义,放心用
  • 代码、YAML、Markdown 列表、SQL:缩进就是语法,用完就坏了

代码类文本要去重,应先在编辑器里做,或用支持「忽略缩进但保留缩进」的工具。这也是为什么通用文本工具永远替代不了格式化工具 —— 两者关心的东西不同。

#排序:为什么 A 在 a 前面

普通排序按 UTF-16 码位逐个比较,而大写字母的码位比小写字母小(A 是 65、a 是 97),所以 Apple 会排在 apple 前面。 这不是 bug,是码位比较的必然结果。

用 文本排序 时的三种情况:

  • 想要大小写不影响顺序:勾「忽略大小写」
  • 中文:既不按拼音也不按笔画,而是按 Unicode 码位(大致等于该字在字符表里的位置)。要拼音序得先把文本转成拼音再排
  • 排序是稳定的:两行排序键相同时保持原相对顺序,不会被随机打乱

排序键取的是每行 trim 后的内容,输出也是这个版本 —— 行首行尾空格会消失。取消勾选「去空白行」后,空行按空字符串处理,升序时会全部挤到最前面。

技巧

顺序建议:先去重再排序。反过来也能得到结果,但重复行会挤在一起占位置,看起来乱;先去重时「保留首次出现」的语义也更符合直觉。

#自然排序解决什么

普通排序把 item10 排在 item2 前面,因为它逐字符比较,1 小于 2。人类习惯的读法正好相反 —— 这就是自然排序存在的理由。

自然排序先把每行切成「连续数字段」和「非数字段」交替比对,数字段按数值大小比:

行普通排序自然排序
item2第 2 位第 1 位
item10第 1 位第 2 位
v1.9在 v1.10 之后在 v1.10 之前

版本号、页码、带序号的商品、章节标题都该用自然排序。而纯文本姓名、地址用普通排序更合适 —— 里面没有数字段,两种方式结果一样。

#批量替换:正则剩下的活

去重和排序只处理「行」,行内的改动要靠替换。 这在清理从网页复制的表格时特别常见:多出来的制表符、括号里的备注、统一的前缀。

用 正则表达式测试 先验证模式,再用 查找替换 执行:

# 去掉行尾的「(已停用)」这类备注
查找:\s*(已停用)$
替换:(留空)

写正则时的三个高频坑:

  • . 不匹配换行:跨行要加 s 标志或用 [\s\S]*?
  • ^ 与 $ 默认不是逐行:多行模式要加 m
  • \d 不认全角数字:从 Excel 粘来的 123 匹配不到,先做全角转半角

替换内容里的 $ 永远是特殊字符(与是否正则模式无关),要输出字面的美元符号得写 $$。

说明

替换是单次遍历,不会对结果再跑一遍。所以 A→B、B→A 这类互换不会死循环,但也一步做不完 —— 要先把 A 换成中间占位符,再换第二次。

#什么时候该用哪个工具

你想做的事用哪个关键差异
去掉重复的名单行文本去重整行判重,会 trim 掉缩进
按字母或数字排序文本排序码位排序,大写在前
版本号、页码按人眼顺序排文本排序选自然排序,数字段按数值比
颠倒行序或字符序文本反转四种模式,多行要选行内反转
确认到底有多少行、多少词文本统计按码点计数,区分字符与字节
验证一个替换模式对不对正则表达式测试支持 g/i/m/s/u 修饰符
执行批量替换查找替换普通模式自动转义元字符

清洗流程建议:统计行数(知道基线)→ 全角转半角 → 去空白行与去重 → 需要时排序 → 行内用替换收尾。 每一步都保留中间结果,出问题能定位到具体一步。

#常见问题

#两条一模一样的行为什么都留下来了?

先逐字符对比,最常见的是行尾多了空格或制表符。去重时虽然会 trim,但如果你看到的是「去重前」的样子,差异可能在其他地方:全角半角(123 与 123)、不间断空格(  粘进来是 U+00A0,看起来和空格一样)、或者零宽字符。用 文本统计 看字符数能快速判断。

#中文排序为什么不是按拼音?

因为它按 Unicode 码位排,码位与拼音无关。要做拼音序,需要先把每个字转成拼音(这需要专门的中文处理库),再按拼音字符串排序,最后映射回原文。浏览器原生排序做不到这件事。

#去重之后行数反而变多了?

检查「显示计数」是否被勾选 —— 它会在每行前面加「次数 + 两个空格」,输出已经不是纯数据了。把带计数的结果再拿去当输入,会被当成新的一批行重新判重。

#想删掉所有空行,用什么?

去重工具默认就会去空白行。如果只想删空行而保留重复行,用 查找替换 的正则模式:查找 ^\s*$\n?,替换留空。多行模式要记得勾。

#反转之后中文变成乱码了?

说明用错了模式。字符反转会把换行也一起倒排,导致行与行错位;而且它按码位拆,由多个码位组合的内容(带肤色的手势、用零宽连接符串起来的家庭 emoji)会散开。多行文本要「每行倒着写」请选行内反转。

本文提到的工具

相关文章