使用awk处理两个文件:同第二字段求和首字段,异则原样输出
解决方案
这是一个典型的用awk处理多文件关联求和的场景,我来给你一个简洁高效的实现方案:
awk ' # 读取第一个文件,累加每个ID对应的数值 NR == FNR { sum[$2] += $1 next } # 处理第二个文件 { if ($2 in sum) { # 若ID在第一个文件存在,累加数值 sum[$2] += $1 } else { # 若ID仅在第二个文件存在,暂存记录 extra[$2] = $1 } } # 输出最终结果 END { # 输出所有在第一个文件出现过的(含与第二个文件的求和结果) for (id in sum) { print sum[id], id } # 输出仅在第二个文件出现的记录 for (id in extra) { print extra[id], id } }' 文件1 文件2
命令逻辑拆解
让我一步步解释这个命令的工作原理,方便你理解和调整:
NR == FNR处理第一个文件:这是awk区分第一个输入文件的经典写法,NR是全局处理的总记录数,FNR是当前文件内的记录数,处理第一个文件时两者相等。此时我们把每条记录的第二字段(即唯一标识ID)作为数组键,将第一字段的数值累加存入sum数组,再用next跳过后续逻辑,专注处理第一个文件。- 处理第二个文件:遍历第二个文件的每条记录时,先检查当前ID是否在
sum数组中:- 如果存在,说明这个ID在第一个文件也有匹配项,直接把当前的第一字段数值加到
sum数组对应的ID值上; - 如果不存在,说明这个ID是第二个文件独有的,我们把它暂存到
extra数组中。
- 如果存在,说明这个ID在第一个文件也有匹配项,直接把当前的第一字段数值加到
END块输出最终结果:所有文件处理完成后,先遍历输出sum数组的内容(包含两个文件共有的ID求和结果,以及第一个文件独有的ID原数值),再遍历输出extra数组的内容(第二个文件独有的ID记录)。
测试结果验证
用你提供的示例文件执行上述命令后,输出结果如下:
6 923000026531 1 923000031178 4 923000050000 4 923000050278 2 923000051178 2 923000060000 1 923335980059
完全匹配你的需求:
- 共有的ID(如
923000050000)的第一字段完成求和(2+2=4); - 仅文件1存在的ID(如
923000031178)原样输出; - 仅文件2存在的ID(如
923335980059)原样输出。
额外扩展说明
这个命令还兼容单个文件内部存在重复ID的场景——如果某个文件里有多个相同的第二字段,sum数组会自动累加同一ID的所有第一字段数值,再和另一个文件的对应ID求和,灵活性拉满。
内容的提问来源于stack exchange,提问作者Muhammad Abdullah
相关产品推荐
相关产品推荐

