comm 和 diff 试图在输入/输出级别完成什么?

comm 和 diff 试图在输入/输出级别完成什么?

给定两个文件,对于每个文件中的每一行,如何做commdiff决定

  • 该行是否也出现在其他文件中?
  • 如果是,它在两个文件中的出现次数是相同还是不同?

考虑每个文件中行之间的顺序?

如何diff确定某一行是“在两个文件中出现但不同”还是“在一个文件中出现但在另一个文件中不出现”?

当两者都用于两个文件的减法时,comm和有何不同?diff

谢谢。

(如果您对一些初等数学不感兴趣,请忽略以下内容。就我的问题而言,以上内容是独立的。)


我猜:

在数学中,集合不会在其元素之间强加顺序。 (如果一个集合是这样的,那么它被称为有序集合,是一个不同的概念)

  • “S1-S2”,即两个集合 S1 和 S2 上的集合差值运算,会产生第一个集合中的元素集合,但不会产生第二个集合中的元素集合。

  • 当求两个集合的交集时,如果一个元素在两个集合中都被考虑,那么它出现在每个集合中的位置并不重要。

文件上也存在类似设置差异的操作,例如comm来自 coreutilsdiff来自 diffutils。但我们不能将文件视为一组行,而应将其视为一组有序的行,因为这些行自然是按其行号排序的。

而且,commdiff的工作方式也各不相同。

在概念层面(输入和输出层面)分别要做什么commdiff尝试完成什么?如果你也可以用数学来解释,那可能会更清楚(我怀疑我可能需要一些关于有序集的基础知识)。我不期望在其实现级别上进行解释,但这可能会有所帮助(某些版本控制和备份软件使用相同或相似的算法进行增量复制)。

谢谢。

答案1

如此处所述; https://en.m.wikipedia.org/wiki/Diff

“diff 的操作是基于解决最长公共子序列问题。”

正如评论中所指出的,有多种实现略有不同(diff、gdiff、vimdiff、git-diff、rdiff-backup 等)。 LCS 的 wiki 页面有您要求的数学定义。从 2 个有序集合中减去所有 LCS,差值就是余数。

答案2

实现的一般问题diff是在检测到删除或插入后找到下一个公共文本块。

为了使结果有用,实现需要决定是否在单行公共代码之后检测到重新同步,或者是否应该有更多公共行。

原因是插入可能包含与插入后已存在的行相同的单行。如果使用单个相同的行来检测重新同步,则差异输出将标记多个插入,这不是人们所期望的。

但发现最长公共字符串不是算法,而是问题,并且有多个解决方案(算法)可以解决该问题。

该命令使用的原始算法find是由 Douglas McIllroy 于 1974 年为 UNIX 编写的。

另一种流行但完全不同的实现(使用不同的算法)是由一些人在 20 世纪 80 年代末为 GNU 编写的。

已知这两种实现在某些情况下会给出不同的结果,因为重新同步算法完全不同。

只要 UNIXdiff使用针对最小代码大小的原始优化,GNUdiff就比 UNIX 更快diff,但是几年前,我将 UNIXdiff实现的优化更改为尽可能快 - 无论代码大小如何,现在只要您将 UNIX 用于典型的文件大小,UNIXdiff就会比 GNU 更快。diff

Douglas McIllroy 使用的算法记录在他的大学主页上:http://www.cs.dartmouth.edu/~doug/diff.pdf

有趣的是,查找差异的逆过程是使用差异输出修补原始文件,以获得该文件的新版本。

SCCS该问题的第一个解决方案是贝尔实验室的 Marc J. Rochkind 于 1972 年发明的程序,请参阅他的解释http://sccs.sourceforge.net/sccs_invention.html在 sccs 主页中:http://sccs.sourceforge.net/由于sccs需要 diff,1974 年之前就有了较旧但不太聪明的diff实现。

请注意,它SCCS使用了一种非常聪明的文件格式,weave可以避免修补文件,因为它允许在单个文件中包含所有可能版本的流。从该文件中提取单个任意版本weave不会导致不同的时间,具体取决于您想要提取的版本 - 它始终以相同的速度完成。

相关内容