使用grep -f匹配两文件重复条目时出现虚假重复记录问题求助
问题原因
- 缺少全行匹配参数:
grep默认执行子串匹配,只要disps.dat的某一行包含pilot.dat中任意一行的内容片段就会命中,并非要求整行完全一致。小样本测试时没有符合子串匹配的无效数据,所以表现正常,大文件数据量上去后就会出现大量误报,即使加了-F固定字符串参数也无法解决子串匹配的问题。 - 模式文件存在空行:如果
pilot.dat中存在空行,空行作为模式串会匹配所有行,直接导致大量无关记录被输出。
高效解决方案
以下方案按大文件处理效率从高到低排序:
方案1:使用comm命令(最优)
comm是专门用于比对两个排序后文件的工具,执行效率远高于逐行匹配和grep多模式匹配,处理百万行级文件也可秒级完成:
# 先对两个文件进行排序 sort pilot.dat > pilot_sorted.dat sort disps.dat > disps_sorted.dat # 提取两个文件的共同行,-12表示同时过滤仅在第一个、第二个文件存在的行 comm -12 pilot_sorted.dat disps_sorted.dat > duplicate.dat
方案2:使用awk命令
awk天然支持全行匹配,不需要处理正则规则,性能优于grep多模式匹配:
# 先读取pilot.dat的所有行存入哈希表,再遍历disps.dat输出存在的行 awk 'NR==FNR {record[$0]++; next} record[$0]' pilot.dat disps.dat > duplicate.dat
方案3:修正grep参数
给grep加上-x参数启用全行匹配,配合之前的-F固定字符串参数即可解决误报问题:
grep -Fxf pilot.dat disps.dat > duplicate.dat
如果文件存在行尾空格、换行符不统一的问题,可以先预处理去掉行尾空白再匹配:
sed 's/[[:space:]]*$//' pilot.dat | grep -Fxf - <(sed 's/[[:space:]]*$//' disps.dat) > duplicate.dat
内容的提问来源于stack exchange,提问作者Ben C Wang
相关产品推荐
相关产品推荐

