如何使用comm命令匹配含相同元素但不同时间戳的日志文件?
解决方法:用
comm找出已安装未卸载的应用 首先得明确comm的核心要求:它的输入文件必须是预先排序好的,这应该是你之前尝试出错的关键原因——如果输入没排序,comm没法正确识别差异,就会出现输出全部列表或者所有内容的情况。
下面是分步实现的方案,全程不用awk:
1. 提取并排序应用列表
先从两个日志文件里分别提取出已安装和已卸载的应用名,同时排序(comm必须依赖排序后的输入):
处理安装日志(假设文件名为install.log)
grep "^Installed:" install.log | sed 's/^Installed: //' | sort > installed_sorted.txt
grep "^Installed:":筛选出所有以Installed:开头的行sed 's/^Installed: //':去掉行首的Installed:前缀,只保留应用名sort:对应用列表排序,满足comm的输入要求
处理卸载日志(假设文件名为remove.log)
grep "^Removed:" remove.log | sed 's/^Removed: //' | sort > removed_sorted.txt
逻辑和上面一致,提取并排序已卸载的应用列表。
2. 用comm对比找出差异
comm默认输出三列:
- 仅在第一个文件中存在的行
- 仅在第二个文件中存在的行
- 两个文件都存在的行
我们需要的是仅在已安装列表里、未出现在卸载列表中的应用,也就是第一列内容,所以用-23选项屏蔽第二、三列:
comm -23 installed_sorted.txt removed_sorted.txt
执行后就能直接得到像flex-old这样的目标差异项。
3. 简化版:不用临时文件(进程替换)
如果不想生成中间文件,可以用Shell的进程替换功能直接串联命令:
comm -23 <(grep "^Installed:" install.log | sed 's/^Installed: //' | sort) <(grep "^Removed:" remove.log | sed 's/^Removed: //' | sort)
这个命令会直接输出结果,省去创建临时文件的步骤。
常见注意事项
- 如果你的日志里应用名存在大小写差异,比如
Flex-Old和flex-old,可以给sort加-f选项忽略大小写,确保匹配准确:sort -f - 一定要确保输入给
comm的文件是排序后的,否则comm的差异判断会完全失效,这是最容易踩的坑!
内容的提问来源于stack exchange,提问作者rrfeva




