基于首列合并多份TSV文件的技术需求及调试求助
批量合并多份TSV文件(基于首列+第二列联合键)
我有多个仅含3列的TSV文件,需要按**首列(Accesion)+第二列(Val)**作为联合键合并,保留表头;对应键存在则保留第三列值,缺失填充NA。文件行数不同、首列无序(可排序)。用join只能处理2个文件,没法批量;自己写的awk脚本没实现需求,以下是示例文件、期望输出和尝试的脚本:
示例输入文件
S01.tsv
Accesion Val S01 AJ863320 1 0.2 AM930424 1 0.3 AY664038 2 0.5
S02.tsv
Accesion Val S02 AJ863320 2 0.8 AM930424 1 0.25 EU236327 1 0.14 EU434346 2 0.2
S03.tsv
Accesion Val S03 AJ863320 5 0.2 EU236327 1 0.5 EU434346 2 0.3
期望输出
Accesion Val S01 S02 S03 AJ863320 1 0.2 NA NA AJ863320 2 NA 0.8 NA AJ863320 5 NA NA 0.2 AM930424 1 0.3 0.25 NA AY664038 2 0.5 NA NA EU236327 1 NA 0.14 0.5 EU434346 2 NA 0.2 0.3
尝试的awk脚本(未实现需求)
BEGIN { OFS="\t" } # tab separated columns FNR==1 { f++ } # counter of files { a[0][$1]=$1 # reset the key for every record for(i=2;i<=NF;i++) # for each non-key element a[f][$1]=a[f][$1] $i ( i==NF?"":OFS ) # combine them to array element } END { # in the end for(i in a[0]) # go thru every key for(j=0;j<=f;j++) # and all related array elements printf "%s%s", a[j][i], (j==f?ORS:OFS) } # output them, nonexistent will output empty
问题分析
原脚本仅将首列作为唯一键,但实际需要Accesion+Val作为联合键(比如AJ863320对应不同Val值是独立条目);同时缺少表头收集、NA填充逻辑,也未实现有序输出。
正确的awk脚本
BEGIN { OFS="\t" # 初始化固定表头 header[1] = "Accesion" header[2] = "Val" } # 处理每个文件的表头 FNR == 1 { file_count++ # 记录当前文件的第三列表头(如S01、S02) col_header[file_count] = $3 header[2 + file_count] = $3 next } # 处理数据行 { # 构建联合键:Accesion + 分隔符 + Val key = $1 "|" $2 # 存储基础信息 keys[key]["acc"] = $1 keys[key]["val"] = $2 # 存储当前文件对应的第三列值 keys[key][file_count] = $3 # 收集所有唯一键 all_keys[key] = 1 } END { # 打印最终表头 for (i=1; i<=length(header); i++) { printf "%s%s", header[i], (i==length(header) ? ORS : OFS) } # 按联合键升序排序输出 PROCINFO["sorted_in"] = "@ind_str_asc" for (k in all_keys) { # 拆分联合键 split(k, parts, "|") acc = parts[1] val = parts[2] printf "%s%s%s", acc, OFS, val # 遍历每个文件,输出对应值或NA for (f=1; f<=file_count; f++) { val_out = (keys[k][f] != "" ? keys[k][f] : "NA") printf "%s%s", OFS, val_out } print "" } }
脚本说明
- 联合键处理:用
Accesion|Val作为唯一标识,区分相同Accesion但不同Val的独立条目; - 表头收集:从每个文件第一行提取第三列表头,拼接成完整输出表头;
- 数据存储:通过多维数组
keys存储每个联合键对应的基础信息和各文件的第三列值; - 有序输出:利用
PROCINFO["sorted_in"]实现联合键的字符串升序排序; - NA填充:遍历每个文件时,若对应键无数据则自动填充NA。
使用方式
将脚本保存为merge_tsv.awk,在终端执行:
awk -f merge_tsv.awk S*.tsv
内容的提问来源于stack exchange,提问作者devbasic
相关产品推荐
相关产品推荐

