在Linux终端中比较两个文件

201

有两个文件名分别为"a.txt""b.txt",它们都有一个单词列表。现在我想检查在"a.txt"中哪些单词是多余的且不在"b.txt"中。

我需要一种高效的算法,因为我需要比较两个字典。


37
仅使用 diff a.txt b.txt 不够吗? - ThanksForAllTheFish
每个文件中的单词可以出现多次吗?您能对文件进行排序吗? - Basile Starynkevitch
我需要的只是那些在“b.txt”中不存在且在“a.txt”中存在的单词。 - Ali Imran
12个回答

403

如果您已经安装了Vim,请尝试以下操作:

vimdiff file1 file2
vim -d file1 file2

你会发现这太棒了!enter image description here


15
当然,这款产品绝对很棒,设计精美且易于发现差异。哦天啊! - Zen
1
你的答案很棒,但我的老师要求我不使用任何库函数:P - Ali Imran
2
多好的工具啊!这非常有帮助。 - user1205577
1
这些颜色的含义是什么? - zygimantus
1
代码着色表示它们在两个文件中是不同的。@zygimantus - Fengya Li
显示剩余2条评论

83

对它们进行排序,然后使用 comm 命令:

comm -23 <(sort a.txt) <(sort b.txt)

comm 用于比较(已排序)的输入文件,并默认输出三列:只存在于a中的行,只存在于b中的行,以及两者共有的行。通过指定-1-2和/或-3,可以抑制相应的输出。因此comm -23 a b仅列出只存在于a中的条目。我使用<(...)语法来实时对文件进行排序,如果它们已经排序,则不需要使用此方法。


我已经添加了自己的答案,仅使用grep命令,请告诉我它是否更有效率? - Ali Imran
3
@AliImran,comm 更高效,因为它可以一次性完成任务,而不需要将整个文件存储在内存中。由于您正在使用的字典很可能已经排序,所以甚至不需要进行sort操作。另一方面,使用 grep -f file1 file2 将会加载整个 file1 到内存中,并将 file2 中的每一行与所有这些条目进行比较,这样效率就大大降低了。它主要适用于小型、未排序的 -f file1 - Anders Johansson
1
感谢@AndersJohansson分享“comm”命令。它确实很方便。我经常需要在文件之间进行外连接,这个命令正好能派上用场。 - blispr
请注意换行符...我刚发现\n也会被包含在比较中。 - Bin

47

如果你喜欢 git diff 的不同输出样式,你可以使用 --no-index 标志来比较不在 git 存储库中的文件:

git diff --no-index a.txt b.txt

使用两个文件,每个文件名字符串约为200k,在这里,我使用了内置的time命令来对比此方法与其他答案:

git diff --no-index a.txt b.txt
# ~1.2s

comm -23 <(sort a.txt) <(sort b.txt)
# ~0.2s

diff a.txt b.txt
# ~2.6s

sdiff a.txt b.txt
# ~2.7s

vimdiff a.txt b.txt
# ~3.2s

comm 显然是迄今为止最快的方法,而对于 diff 风格的输出来说,git diff --no-index 看起来是最快的方法。


更新 2018-03-25:你实际上可以省略 --no-index 标志,除非你在 git 存储库内部并想要比较该存储库中未跟踪的文件。从man pages获得以下信息:

此形式用于比较文件系统上给定的两个路径。当在 Git 控制的工作树中运行命令,并且至少有一个路径指向工作树之外时,或者在 Git 控制之外的工作树中运行命令时,可以省略 --no-index 选项。


37

尝试使用sdiff (man sdiff)命令

sdiff -s file1 file2

34

在Linux中,您可以使用diff工具来比较两个文件。您可以使用--changed-group-format--unchanged-group-format选项来过滤所需的数据。

以下三个选项可用于为每个选项选择相关组:

  • '%<' 从FILE1获取行

  • '%>' 从FILE2获取行

  • '' (空字符串) 用于从两个文件中删除行。

例如:diff --changed-group-format="%<" --unchanged-group-format="" file1.txt file2.txt

[root@vmoracle11 tmp]# cat file1.txt 
test one
test two
test three
test four
test eight
[root@vmoracle11 tmp]# cat file2.txt 
test one
test three
test nine
[root@vmoracle11 tmp]# diff --changed-group-format='%<' --unchanged-group-format='' file1.txt file2.txt 
test two
test four
test eight

9
你还可以使用:colordiff:以彩色显示diff的输出。
关于vimdiff:它允许你通过SSH比较文件,例如:
vimdiff /var/log/secure scp://192.168.1.25/var/log/secure

提取自:http://www.sysadmit.com/2016/05/linux-diferencias-entre-dos-archivos.html

在Linux中,有两种常见的文件类型:普通文件和目录。它们之间的区别在于普通文件包含数据,而目录是包含其他文件或目录的文件夹。

普通文件可以分为文本文件和二进制文件。文本文件包含了可读的文本,如配置文件和脚本文件。而二进制文件则包含了编译过的程序代码,无法直接阅读。

此外,在Linux中还有一些特殊类型的文件,如符号链接和设备文件。符号链接类似于Windows中的快捷方式,指向其他文件或目录。而设备文件代表着系统硬件设备,如磁盘驱动器和打印机。


8

4
使用comm -13(需要排序文件):
$ cat file1
one
two
three

$ cat file2
one
two
three
four

$ comm -13 <(sort file1) <(sort file2)
four

3

您还可以使用:

sdiff file1 file2

在终端中并排显示差异!


2
diff a.txt b.txt | grep '<'

然后可以使用管道操作将结果传递给“cut”命令,以获得干净的输出。
diff a.txt b.txt | grep '<' | cut -c 3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接