toolgarden.xyz
EN
diff 算法文本对比增删改开发工具

文本对比工具原理:diff 算法怎么找出增删改

diff 算法会寻找两段文本之间尽量长的共同部分,再把剩余内容标记为新增、删除或修改,用于代码、日志、文案和配置对比。

ToolGarden 推荐的工具优先在浏览器本地运行,文件和文本不必上传到服务器,适合更注重安全隐私的日常处理。

发布于 2026年7月2日更新于 2026年8月3日约 7 分钟阅读作者 ToolGarden

diff 算法的目标不是理解文本含义,而是找出两个序列里哪些部分相同,哪些部分发生了变化。

实际使用时,先把旧版本放在左侧、新版本放在右侧,再选择适合内容的比较粒度。行级结果适合快速定位段落,词级高亮则负责指出同一行内部究竟改了哪个词。两级结合,既能看到整体结构,也不会漏掉数字、状态或措辞变化。

先看一个可复现的例子

旧版本
Checkout success
Payment pending
Send email receipt

新版本
Checkout success
Payment completed
Send email receipt

行级比较会把第二行标记为一处删除和一处新增;词级比较继续在这一行里对齐共同的 Payment,只高亮 pending 与 completed。人工扫长日志时最容易漏掉的,正是这种行结构不变但关键状态已经变化的情况。

基本思路

  1. 先把文本拆成行、词或字符。
  2. 寻找两份内容中可以对齐的共同部分。
  3. 共同部分之间的缺口标记为新增或删除。
  4. 相邻的删除和新增通常可以被展示为修改。
  5. 最后把结果渲染成高亮视图。

行级、词级、字符级有什么区别?

粒度适合内容特点
行级日志、配置、列表速度快,结构清楚
词级文案、说明、句子能看出一句话里改了哪个词
字符级短字符串、标识符很细,但长文本会显得碎
结构化JSON、对象数据按字段路径比纯文本更准确

很多 diff 实现会使用最长公共子序列或类似策略。它们尽量保留共同内容,再用最少的插入和删除说明变化。

如何减少无意义的差异

  • 先统一换行符与文件编码,避免 Windows CRLF 和 Unix LF 造成整段变化。
  • 对日志先去掉每行都会变化的时间戳、请求 ID 或随机值,再比较真正有用的内容。
  • 两份 JSON 应改用结构化 JSON 对比,缩进和字段顺序不应该成为差异。
  • 整段移动通常会显示为原位置删除、新位置新增,结果并不表示内容被改写。
  • 超长文件先按章节或时间范围切小,浏览器更容易计算,人工复核也更聚焦。

把 diff 当作审查线索,而不是结论

算法只能证明文本序列不同,不能判断改动是否正确。审查配置时要确认单位与环境,审查文案时要检查上下文,审查代码生成结果时还要运行对应验证。对于看似只有一个字符的变化,尤其要留意版本号、小数点、负号和权限值。

常见问题

Q.为什么两段文本明明只改了一个字,diff 工具却显示整行都变了?

这是行级 diff 的正常行为。行级 diff 把文本按换行符切成块,然后逐行比较:只要一行里任何一个字符不同,整行就被标记为删除加新增。要看清具体改了哪个字,需要切换到词级 diff 或字符级 diff。词级 diff 会把行内容再切成单词,只高亮改动的词;字符级 diff 更细,能显示单个字母或汉字变化。ToolGarden 文本对比支持切换粒度。对代码或配置文件用行级,对文案或句子用词级更合适。

Q.diff 结果里出现大量“删除+新增”而不是“修改”,正常吗?

正常。经典 diff 算法(Myers 算法、LCS 变种)只输出插入和删除两种操作,“修改”是渲染层把相邻的删除和新增合并显示出来的。如果你的两段文本中,相同内容之间穿插着大量不同内容,算法找不到足够长的公共子序列,就会把大块内容标记为整块删除加整块新增,看起来像“全部改了”。这时可以试试:调整 diff 粒度(词级、字符级)、或者对齐两段文本的段落顺序再对比,能减少虚假差异。

Q.对比 JSON 数据时,为什么应该用 JSON diff 而不是文本 diff?

JSON 是结构化数据,字段顺序、缩进、空格都可以变化而不影响语义。文本 diff 会把这些格式差异当成真差异:同一份 JSON 只是重新格式化了一次,文本 diff 就报出满屏改动。JSON diff 先把两份 JSON 解析成对象树,再按字段路径(比如 user.address.city)比较值,忽略格式和字段顺序。这样你看到的差异才是真正的数据变化:某个字段从 A 变成 B、某个字段新增、某个数组多了一项。做接口回归、数据校对时,JSON diff 效率高得多。

Q.diff 工具能理解代码语义(比如变量重命名)吗?

标准 diff 不能。经典算法只看字符或行是否相同,不理解语言语法。把变量 userName 改成 user_name,diff 只会告诉你“这行删了 userName,加了 user_name”,不知道是同一个变量的重命名。要做语义级对比,需要专门的工具:GitHub 的 semantic diff、JetBrains IDE 的结构化 diff、AST diff 工具(如 gumtree、difftastic)会把代码解析成语法树后再比较。日常开发中 diff 已经够用,涉及大规模重命名或重构时才需要更高级的工具。

Q.两个很长的文件 diff 时,工具很慢或卡住,能优化吗?

diff 算法的最坏时间复杂度是 O(N×M),两个文件都有几万行时计算量就会爆炸。优化思路有几个:一是先按段落或章节手动切分,只对比变化的部分;二是关闭词级或字符级 diff,只做行级;三是用命令行工具 diff 或 git diff,它们对大文件优化更好;四是如果两文件差异集中在少数几处,用搜索定位后局部对比比整体对比快得多。浏览器端 diff 通常适合几千行以内的文本,超出时改用桌面工具。