逐行比较两个文件,并在另一个文件中生成差异

我想比较file1和file2,并生成一个file3,其中包含file1中不存在于file2中的行。

diff(1)不是答案,但comm(1)是。

NAME comm - compare two sorted files line by line SYNOPSIS comm [OPTION]... FILE1 FILE2 ... -1 suppress lines unique to FILE1 -2 suppress lines unique to FILE2 -3 suppress lines that appear in both files 

所以

 comm -2 -3 file1 file2 > file3 

input文件必须被sorting。 如果不是,先sorting。 这可以用临时文件来完成,或者…

 comm -2 -3 <(sort file1) <(sort file2) > file3 

前提是你的shell支持进程replace(bash)。

Unix实用程序diff就是为了这个目的。

 $ diff -u file1 file2 > file3 

有关选项和不同的输出格式等,请参阅手册和Internet。

考虑一下:
文件a.txt:

 abcd efgh 

文件b.txt:

 abcd 

你可以find与以下的区别:

 diff -a --suppress-common-lines -y a.txt b.txt 

输出将是:

 efgh 

您可以使用以下命令重新确定输出文件(c.txt)中的输出:

 diff -a --suppress-common-lines -y a.txt b.txt > c.txt 

这将回答你的问题:

“…其中包含file1中不存在于file2中的行。”

有时diff是你需要的效用,但是有时候比较合适。 这些文件需要预先sorting,如果您使用的是支持bash,ksh或zsh等进程replace的shell,则可以进行即时sorting。

 join -v 1 <(sort file1) <(sort file2) 

使用Diff实用程序并仅提取输出中以<开头的行

已经有很多答案,但没有一个完美的恕我直言。 Thanatos的答案每行留下一些额外的字符,Sorpigal的答案要求对文件进行sorting或预先sorting,这在所有情况下可能都不够。

我认为获取不同的行的最好的方法是不同的(没有额外的字符,不重新sorting)是diffgrepawk (或类似的)的组合。

如果行不包含任何“<”,则简短的一行可以是:

 diff urls.txt* | grep "<" | sed 's/< //g' 

但是会从行中删除“<”(小于,空格)的每个实例,这并不总是可以的(例如,源代码)。 最安全的select是使用awk:

 diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}' 

这个一行代码差别这两个文件,然后过滤出ed样式的diff输出,然后删除diff添加的尾随“<”。 即使这些行本身包含一些“<”,也可以工作。

如果你需要用coreutils解决这个问题,那么接受的答案是好的:

 comm -23 <(sort file1) <(sort file2) > file3 

你也可以使用sd (stream diff),它不需要sorting,也不需要进程replace,支持无限stream,如下所示:

 cat file1 | sd 'cat file2' > file3 

这个例子可能没有那么多的好处,但仍然考虑到这一点; 在某些情况下,您将无法使用comm grep -Fdiff

这里是我写的关于在terminal上引入sd的terminalstream分类的博文。

尝试

 sdiff file1 file2 

它在大多数情况下对我来说通常效果更好。 如果行顺序不重要(例如某些文本configuration文件),您可能需要先对文件进行sorting。

例如,

 sdiff -w 185 file1.cfg file2.cfg 
 diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt 

我在这个线程中尝试了几乎所有的答案,但没有一个是完整的。 在一个以上的path之后为我工作。 差异会给你的区别,但有一些不必要的特殊的经历。 实际的差异线以“>”开头。 所以下一步是grep行以'>'开始,然后删除sed