如何使用awk处理四个文件,提取所有文件共有及非共有ID?
多文件ID交集与差集提取方案
我有四个文件,需要提取所有文件中均存在的ID,目前已经实现了处理两个文件的awk代码:awk 'FNR==NR { a[$1]; next } $1 in a' file2 file1,想知道怎么扩展到四个文件;同时还需要提取并非所有文件都存在的ID。
示例文件内容
file1 ID_1 ID_3 ID_4 file2 ID_3 ID_2 ID_4 file3 ID_6 ID_3 ID_4
一、提取所有文件共有的ID
处理多文件交集的核心思路是统计每个ID出现在多少个不同文件中,当计数等于文件总数时,就是所有文件都存在的ID。
适用于4个文件的awk命令:
awk '{ ids[$1] } ENDFILE { for (id in ids) cnt[id]++ } END { for (id in cnt) if (cnt[id] == ARGC-1) print id }' file1 file2 file3 file4
代码说明
{ ids[$1] }:遍历每个文件的行,把当前ID存入ids数组(自动去重,同一文件内重复ID只保留一次)ENDFILE { ... }:每处理完一个文件,就把该文件里记录的所有ID的计数加1END { ... }:所有文件处理完成后,遍历计数数组cnt,输出计数等于文件总数(ARGC-1是因为ARGC包含awk命令本身,减去1就是传入的文件数量)的ID
示例输出(对应3个文件的情况)
ID_3 ID_4
二、提取并非所有文件都存在的ID
这部分需求和交集相反,可通过两种方式实现:
方法1:基于计数直接过滤
直接输出计数不等于文件总数的ID:
awk '{ ids[$1] } ENDFILE { for (id in ids) cnt[id]++ } END { for (id in cnt) if (cnt[id] != ARGC-1) print id }' file1 file2 file3 file4
方法2:通过“全集减交集”实现
先提取所有去重的ID,再排除掉交集里的ID:
awk 'NR==FNR { exclude[$1]; next } !($1 in exclude) { print $1 }' <(awk '{ ids[$1] } ENDFILE { for (id in ids) cnt[id]++ } END { for (id in cnt) if (cnt[id]==4) print id }' file1 file2 file3 file4) <(cat file1 file2 file3 file4 | sort -u)
内容的提问来源于stack exchange,提问作者hsa
相关产品推荐
相关产品推荐

