文本逐行对比

并排找出两版文本的新增与删除行

图例:- 删除 + 新增 空格 相同

文本对比的原理:LCS 算法、行级比较与噪声处理

为什么按行比,而不是按字符比

字符级对比在一行内容改动一个字时,能精确显示是哪几个字变了;但在代码、配置、CSV 这类结构化文本上,字符级会出现大量无意义的碎片——把行尾的一个逗号改成换行,字符 diff 会标出整行被改,而人想看的是"这一行变了"。

行级对比是工程实践中的默认选择:每一行作为一个不可分割的单元来比较,输出"哪些行删除了、哪些行新增了、哪些行保持不变"。这与 git diff、diff -u、代码评审界面用的都是同一套粒度。

LCS:怎么算出"最少改几行"

行级 diff 的核心是最长公共子序列(Longest Common Subsequence)。思路是:找出两个版本共同拥有的、顺序一致的最长行序列,这些行就是"没变的部分";剩下的行就是插入或删除。

举例,原文三行 A B C,新文三行 A C D:

结果解释
公共子序列A C顺序一致且都出现,长度 2,这是最长的
删除B只在原文里
新增D只在新文里

算法上用动态规划填一张 n×m 的表(n、m 是两个版本的行数),然后回溯找出这个子序列。所以计算量是行数的乘积级:两个 1000 行的文件需要百万级次比较,很快;两个 100000 行的文件就是百亿级,会明显变慢。工具的表格法实现正是这个复杂度,处理上万行的文件没问题,再大建议改用 git diff 或专门的 diff 库(它们通常加了块级预筛选来跳过未变区域)。

它无法判断"移动"

这是 LCS 类算法的固有局限:把一个段落从文件开头移到结尾,会被报告成"在开头删除"加"在结尾新增",而不是"移动"。

后果是重构类的改动(调整函数顺序、整理配置分组)看起来像大改,而实际上逻辑没变。有些高级 diff 工具会做移动检测(把相同的块配对起来标注为移动),但那需要额外的启发式判断,也可能误判。看到大段红色加绿色时,先判断是不是纯粹的顺序调整。

噪声来源与处理

噪声症状处理
行尾空白差异整行被标记为改动,肉眼看不出区别比较前统一去掉行尾空白
制表符与空格混用缩进看起来一样,实际不同统一缩进字符,或用忽略空白的比较模式
换行符差异整个文件全部标记为不同CRLF(Windows)与 LF(Unix)必须统一
文件编码差异中文全部乱码或全部标红确认两边都是 UTF-8(BOM 有无也要一致)
重新格式化逐行都不同但内容等价先跑一遍格式化再比,或比较格式化后的结果

第三行是最容易踩的:一个用 Windows 编辑器保存、另一个在 Linux 上导出,两边逐行内容完全相同但行尾各带一个 \r,结果是全文件标红——这种情况看起来像"什么都被改了",实际只是换行符。工具会按行内容精确比较,所以遇到"全红但看不出区别"时,先检查换行符。

几个实用做法

工具怎么用

  1. 左边放原始(旧)文本,右边放对比(新)文本,每行一条。
  2. 点对比,输出会标记出删除行、新增行和相同行三类。
  3. 图例在按钮下方,颜色与含义对应。

比较在浏览器本地完成,两个版本的文本都不会被上传。这对比较含有客户数据、密钥或内部配置的文件是必要的前提。

常见问题

对比算法是什么?

基于最长公共子序列(LCS)的逐行 diff,能稳定找出新增、删除与相同的行,适合版本对比。

为什么有些行被标记为删除而不是修改?

本工具按整行比较,一行内容有变化就视为"旧行删除 + 新行新增",不会做行内字符级比对。