文本差异对比(逐行 diff · 新增删除一目了然)
把两段文本按行对齐,用精确的最长公共子序列算出哪些行新增、哪些行删除、哪些行未变,并给出相似度,可勾选忽略行尾空白与大小写。对比全在浏览器本地完成,贴进来的文本不会离开这台设备。
—
新增行
—
删除行
—
未变行
—
相似度
| 行号(原) | 行号(新) | 状态 | 内容 |
|---|
逐行对比的口径
这两段文字到底哪里不一样
「这两段文字到底哪里不一样」——肉眼扫过去只会得出"好像差不多",而真正改动的往往恰好是漏掉的那个逗号、少掉的那一行配置。
两段文本先切成行,用最长公共子序列(LCS)把它们对齐,再按顺序给出:哪几行被删了、哪几行是新加的、哪些行原样不动。四个格子给出总量(新增 / 删除 / 未变 / 相似度),表格给出逐行的落点。
适合的是"改动前后各一小段":文章改稿、配置文件与已知正确版本比对、新旧两版报错日志、写变更说明之前先确认自己到底动了什么。它不是 git diff,也没有词级高亮,只保证"行"这一层的结论是精确算出来的。
计算口径
- 换行先归一:
\r\n(Windows)和\r(老 Mac)统一换成\n,再按\n切行;行内其余字符一概原样保留、原样显示。 - 一行是一个整体:两个"行键"完全相等才算未变。默认行键就是整行文本;勾「忽略行尾空白」时先去掉行尾空白,勾「忽略大小写」后再统一转小写。归一只参与判定,表格里显示的是你贴进来的原始行。
- 对齐用精确 LCS 动态规划:
dp[i][j]表示"原文从第 i 行、修改后从第 j 行开始,往后还能对上多少行",自底向上填满整张表再回溯,得到一串顺序排列的「未变 / 删除 / 新增」操作。单侧限 1200 行,表最大 1201×1201,所以这里是真精确解,不含启发式。 - 改写会拆成两行:没被 LCS 匹配上的原文行记为「删除」,没被匹配上的修改后行记为「新增」。中间一行改了字,输出就是"删掉旧行 + 加上新行"两条,而不是一条"修改"。
- 相似度 = 2 × |LCS| ÷(左行数 + 右行数)× 100,保留 1 位小数。两边各 10 行且完全一致是 100.0%;一边 100 行、一边 1 行且那行能对上,是 2 × 1 ÷ 101 ≈ 2.0%。它衡量的是行数加权的重合度,不是字符级相似度。
- 行号:未变的行两侧都有行号,删除的行只有「行号(原)」,新增的行只有「行号(新)」,空出来的那格用 — 占位。行号从 1 开始数。
- **取消「显示未变化的行」**时表格只留新增与删除,提示里会写明藏起了多少行未变内容。一次最多渲染 3000 行,超了会明确说明只画了前 3000 行;统计数字始终是全部算完的结果。
- 空行也算一行:文本结尾那个换行会产生一个空行,切分时不会替你删掉它。空行在「内容」列显示为空白格,行号照常给出。
什么时候这个结果会骗你
- 只看行不看字:一个句号改成逗号,也算"删除一整行 + 新增一整行"。要看词级差别请回编辑器。
- 整段挪位置会被判成"删了又加":LCS 只保证公共子序列最长,它不知道你把那段说明往上搬了二十行。如果新增行数与删除行数恰好相当,先怀疑是顺序动了。
- 相似度对行数差很敏感:万行文本里加 3 行仍然显示 99.9%,但那 3 行可能才是要害;反过来短文本改一个词就能掉到 80%。它是概览指标,不是质量评分。
- 忽略选项会造出假"未变":勾了忽略大小写,
userId和userid就是同一行——代码里它们可是两个东西。「忽略行尾空白」只管行尾,缩进不同、Tab 与空格的差别照旧算改动。 - 它不认识结构:JSON 换了键的顺序、Markdown 换了折行位置、注释和代码混排,都会显示成实打实的差异。
- 1200 行是硬闸门:越线直接拒绝计算,不会给你一份"看起来完整"其实被砍过的结果。
常见问题
Q:中间那行只改了两个字,为什么占两行? 因为经典 diff 的输出就是编辑脚本:先求最长公共子序列,剩下匹配不上的自然分成删除与新增。只有真能对上账的行才叫未变,这样「新增 / 删除 / 相似度」三个数之间才自洽。
Q:相似度 100.0% 是不是等于两段文本一模一样? 在没勾任何忽略选项时是。勾了之后,100.0% 只代表"在忽略行尾空白 / 大小写的口径下每行都能对上",行内空格与字母大小写仍可能不同——把「显示未变化的行」打开逐行看一眼就知道了。
Q:几千行的文件怎么比? 先缩小范围,只贴真正相关的那一段(控制在单侧 1200 行以内),或先用编辑器定位再截上下文。宁可拒绝计算,也不给一份不完整的结果。
Q:我贴进来的文本去了哪? 切行、对齐、渲染都跑在这段脚本里,不会拿你的文本去发请求,文本不会离开这台设备。