菜鸟科技网

Linux comm命令如何精准比较两文件内容?

comm 是一个用于比较两个已排序文件的命令,它的名字来源于 "common"(共同的),它的主要功能是逐行比较两个文件,并输出三列结果:

Linux comm命令如何精准比较两文件内容?-图1
(图片来源网络,侵删)
  1. 仅在第一个文件中出现的行
  2. 仅在第二个文件中出现的行
  3. 两个文件中都出现的行(交集)

语法

comm [选项] 文件1 文件2

重要前提: comm 要求输入的两个文件都必须是已排序的,并且通常是按行首字符的 ASCII 码顺序排序的,如果文件未排序,输出结果将是无意义的。


选项

comm 命令的选项非常直观,它们控制着三列输出的显示方式,默认情况下,三列都会显示。

选项 全称 描述
-1 --suppress-column1 不显示第一列(仅在文件1中出现的行)
-2 --suppress-column2 不显示第二列(仅在文件2中出现的行)
-3 --suppress-column3 不显示第三列(两个文件共有的行)

这些选项可以自由组合。-12 表示同时隐藏第一列和第二列,这样输出就只包含两个文件的交集了。


输出格式

comm 的默认输出格式是使用 Tab 键来分隔三列数据:

Linux comm命令如何精准比较两文件内容?-图2
(图片来源网络,侵删)
[仅在文件1中的行]  [仅在文件2中的行]  [共有的行]
  • 如果某一行只在文件1中,那么第二列和第三列将是空的。
  • 如果某一行只在文件2中,那么第一列和第三列将是空的。
  • 如果某一行在两个文件中都存在,那么只有第三列会有内容。

实战示例

为了演示,我们先创建两个示例文件,并对它们进行排序。

# 创建文件1
echo "apple" > file1.txt
echo "banana" >> file1.txt
echo "orange" >> file1.txt
echo "grape" >> file1.txt
# 创建文件2
echo "banana" > file2.txt
echo "kiwi" >> file2.txt
echo "orange" >> file2.txt
echo "pear" >> file2.txt
# 对文件进行排序 (这是使用 comm 的前提!)
sort file1.txt -o file1.txt
sort file2.txt -o file2.txt
# 查看文件内容
echo "--- file1.txt ---"
cat file1.txt
echo "--- file2.txt ---"
cat file2.txt

如下:

--- file1.txt ---
apple
banana
grape
orange
--- file2.txt ---
banana
kiwi
orange
pear

现在我们来使用 comm 命令。

示例 1:默认输出(显示所有三列)

comm file1.txt file2.txt

输出:

Linux comm命令如何精准比较两文件内容?-图3
(图片来源网络,侵删)
apple                     banana                    grape
                    kiwi                    orange
                                        pear

解读:

  • applegrape 只在 file1.txt 中,所以出现在第一列。
  • kiwipear 只在 file2.txt 中,所以出现在第二列。
  • bananaorange 在两个文件中都有,所以出现在第三列。

示例 2:只显示交集(两个文件共有的行)

使用 -12 选项来隐藏第一列和第二列。

comm -12 file1.txt file2.txt

输出:

banana
orange

这是 comm 命令一个非常常见的用法,用来查找两个文件的共同内容。

示例 3:只显示在 file1 中但不在 file2 中的行

使用 -23 选项来隐藏第二列和第三列。

comm -23 file1.txt file2.txt

输出:

apple
grape

示例 4:只显示在 file2 中但不在 file1 中的行

使用 -13 选项来隐藏第一列和第三列。

comm -13 file1.txt file2.txt

输出:

kiwi
pear

commdiffgrep 的比较

commdiffgrep 都可以用来比较文件,但它们的目的和输出方式不同。

命令 主要用途 输出特点
comm 比较两个已排序文件,找出独有共有的行。 输出三列,结构化,易于脚本处理。
diff 比较两个文件的差异(添加、删除、修改)。 输出详细的补丁格式(a for add, c for change, d for delete),适合人类阅读和 patch 命令。
grep 使用模式匹配来查找行。 通常通过管道组合使用,grep -f file1.txt file2.txt 来查找 file2 中包含 file1 内容的行。

常见用法与脚本技巧

comm 的真正威力在于它在 shell 脚本中的组合使用。

用法1:查找两个文件的交集(并排序)

comm -12 <(sort file1.txt) <(sort file2.txt)
  • <(...) 是进程替换(Process Substitution),它允许将命令的输出像文件一样传递给另一个命令,这样你就不需要手动创建临时排序文件了。

用法2:查找在 file1 中但不在 file2 中的所有行

comm -23 <(sort file1.txt) <(sort file2.txt)

这在很多场景下非常有用,

  • 找出系统中已安装但某个软件包列表中没有的软件包。
  • 找出一份完整名单中缺失的条目。

用法3:查找两个文件的并集(去重后合并)

这个技巧稍微复杂一点,需要将 comm 的输出重新组合。

# 合并第一列和第二列,然后与第三列合并,最后再次排序去重
comm -12 file1.txt file2.txt | cat - <(comm -23 file1.txt file2.txt) <(comm -13 file1.txt file2.txt) | sort -u

或者更简洁地使用 sort 命令直接实现:

sort file1.txt file2.txt | uniq

可以看到,对于简单的并集和交集,sort + uniq 的组合通常更直接。


特性 描述
核心功能 比较两个已排序文件,输出独有和共有的行。
前提条件 输入文件必须已排序
输出格式 三列,用 Tab 分隔。
主要优势 结构化输出,非常适合在 shell 脚本中进行后续处理,例如提取某一列。
常用场景 查找交集(comm -12)、查找差异(comm -23 / comm -13)。
替代方案 对于未排序的文件,可以使用 grepdiff,对于集合操作(并集、交集、差集),sort + uniq 的组合通常更通用和强大。

comm 的核心是“比较已排序文件”,它是一个小巧但功能强大的工具,掌握它能让你在处理文本文件时更加得心应手。

分享:
扫描分享到社交APP
上一篇
下一篇