You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于首列合并多份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 ""
    }
}

脚本说明

  1. 联合键处理:用Accesion|Val作为唯一标识,区分相同Accesion但不同Val的独立条目;
  2. 表头收集:从每个文件第一行提取第三列表头,拼接成完整输出表头;
  3. 数据存储:通过多维数组keys存储每个联合键对应的基础信息和各文件的第三列值;
  4. 有序输出:利用PROCINFO["sorted_in"]实现联合键的字符串升序排序;
  5. NA填充:遍历每个文件时,若对应键无数据则自动填充NA。

使用方式

将脚本保存为merge_tsv.awk,在终端执行:

awk -f merge_tsv.awk S*.tsv

内容的提问来源于stack exchange,提问作者devbasic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 03:54:23