使用awk/sed基于两列对比三个文件并输出各文件唯一条目
嘿,这个需求我熟!要对比三个格式一致的文件,基于前两列追踪每个条目在几个文件里出现、具体是哪些文件对吧?用awk就能完美解决,下面给你一步步拆解:
解决方案:用AWK实现跨文件条目追踪
核心思路
- 把前两列拼接成唯一标识(毕竟我们要基于这两列做对比)
- 遍历所有输入文件,给每个标识记录对应的文件名(自动去重同一文件内的重复条目)
- 最后统一输出:原始行内容 + 出现的文件数量 + 具体文件名列表
完整AWK脚本
先写个可复用的脚本文件(比如叫track_entries.awk),方便后续调用:
BEGIN { FS = OFS = "\t" # 这里默认是制表符分隔,如果你是逗号分隔,改成FS=","即可 } { # 用前两列生成唯一键,确保相同前两列的条目被归为一组 key = $1 FS $2 # 避免同一文件内的重复条目被多次统计 if (!(FILENAME in files[key])) { files[key][FILENAME] = 1 lines[key] = $0 # 保存该行的完整内容 } } END { # 遍历所有统计好的条目 for (key in lines) { # 计算该条目出现的文件数量 count = length(files[key]) # 把文件名拼接成易读的字符串 file_list = "" for (fname in files[key]) { file_list = file_list (file_list ? ", " : "") fname } # 按要求输出:原始行 + 文件数量 + 文件名列表 print lines[key], count, file_list } }
使用方法
假设你的三个文件是file1.txt、file2.txt、file3.txt,直接在终端运行:
awk -f track_entries.awk file1.txt file2.txt file3.txt
嫌写脚本麻烦的话,也可以直接用单行命令:
awk 'BEGIN{FS=OFS="\t"}{key=$1 FS $2; if(!(FILENAME in files[key])){files[key][FILENAME]=1; lines[key]=$0}}END{for(key in lines){count=length(files[key]); file_list=""; for(fname in files[key]){file_list=file_list (file_list?", ":"") fname}; print lines[key], count, file_list}}' file1.txt file2.txt file3.txt
细节调整说明
- 分隔符适配:如果你的文件是逗号/空格分隔,把
FS = OFS = "\t"改成对应的分隔符即可(比如逗号就写FS = OFS = ",")。 - 同一键多内容处理:如果同一个前两列组合在不同文件里的后续列内容不一样,脚本默认会保存最后一个文件里的行内容。要是想保留所有行内容,把
lines[key] = $0改成lines[key] = lines[key] (lines[key] ? "\n" : "") $0就行。 - 取消文件内去重:要是不需要同一文件内的重复条目去重,删掉
if (!(FILENAME in files[key]))这个判断条件就可以了。
示例演示
比如三个输入文件:file1.txt:
apple red sweet banana yellow soft
file2.txt:
apple red crisp orange orange juicy
file3.txt:
banana yellow firm orange orange sour
运行脚本后,输出结果如下:
apple red sweet 2 file1.txt, file2.txt banana yellow soft 2 file1.txt, file3.txt orange orange juicy 2 file2.txt, file3.txt
内容的提问来源于stack exchange,提问作者aan
相关产品推荐
相关产品推荐

