逐行比较两个文件,并在另一个文件中生成差异
我想比较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)是diff
, grep
和awk
(或类似的)的组合。
如果行不包含任何“<”,则简短的一行可以是:
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 -F
或diff
。
这里是我写的关于在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 。