Shell Daily 2025-12-27: 集合运算 (Comm)
处理文本数据时,我们经常遇到这种需求:给你两份名单(比如 all_hosts.txt 和 patched_hosts.txt),请迅速找出哪些主机还没打补丁(即在 A 中但不在 B 中)。
手写 Python 脚本或者用复杂的 grep -v 循环都太慢了。Shell 哲学里有一个专门处理“集合运算”的神器——comm。
怎么用
comm 逐行比较两个已排序的文件,默认输出三列:
- 仅在文件 A 的行
- 仅在文件 B 的行
- A 和 B 共有的行
通过参数 -1, -2, -3 可以屏蔽掉对应的列,从而组合出交集、差集。
- 语法:
comm [options] file1 file2 - 关键前提:输入的两个文件必须先经过
sort排序,否则结果不准确。 - 兼容性:POSIX 通用标准。所有 Unix-like 系统标配。
适用场景
- 白名单过滤:从全量日志中剔除已知合法的 IP 列表。
- 版本比对:快速找出两个配置文件的共同配置项或差异项。
示例 1:找出未完成的任务 (差集 A - B)
假设 total.txt 是总任务,finished.txt 是已完成任务。我们要找出剩下的任务:
# 这里的逻辑是:
# -2 屏蔽“仅在 finished.txt”的(没意义)
# -3 屏蔽“两者都有”的(已完成的)
# 剩下的就是 -23:仅在 total.txt 出现的(未完成的)
comm -23 sorted_total.txt sorted_finished.txt
示例 2:找出共同好友 (交集 A ∩ B)
找出两个用户关注列表里的共同关注者:
# -1 屏蔽 user_a 独有的
# -2 屏蔽 user_b 独有的
# 剩下的 -12 就是两者共有的
comm -12 user_a_follows.txt user_b_follows.txt
(注:配合之前讲的进程替换 <(...),你可以直接写 comm -23 <(sort A) <(sort B),连中间文件都不用存,非常丝滑。)