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

如何在Bash中从多个TSV表的列生成新合并表?

解决方法

方法一:用cut+paste(简单易理解)

这种方法依赖基础文本处理命令,步骤清晰,适合快速上手:

  1. 从第一个TSV文件提取name列作为新表的首列:
cut -f1 first_sample.tsv > name_col.tmp

将first_sample.tsv替换成你的任意一个目标文件名即可。

  1. 遍历所有TSV文件,提取每个文件的第5列(reads列)并保存为临时文件:
for f in *.tsv; do
    cut -f5 "$f" > "${f%.tsv}_reads.tmp"
done

${f%.tsv}会自动去掉文件名的.tsv后缀,生成的临时文件会以xxx_reads.tmp命名。

  1. 用paste命令将name列和所有reads临时文件按行合并,生成最终表格:
paste name_col.tmp *_reads.tmp > reads_table.tsv
  1. 清理临时文件:
rm name_col.tmp *_reads.tmp

方法二:用awk(高效无临时文件)

针对50个文件的场景,awk可以一次性处理所有文件,无需生成临时文件,效率更高:

awk -F'\t' '
    # 处理表头行
    FNR == 1 {
        if (NR == FNR) {
            # 第一个文件:输出表头,首列为name,后续列为去掉.tsv后缀的文件名
            printf "name"
            for (i=1; i<ARGC; i++) {
                sub(/\.tsv$/, "", ARGV[i])
                printf "\t%s", ARGV[i]
            }
            print ""
        }
        next  # 跳过所有文件的表头行
    }
    # 处理第一个文件的内容:存储name列到数组
    NR == FNR {
        name[FNR] = $1
        next
    }
    # 处理其他文件:存储对应行的reads列(第5列)
    {
        reads[ARGIND][FNR] = $5
    }
    # 最终输出所有内容
    END {
        for (line=2; line<=length(name); line++) {
            printf "%s", name[line]
            for (file_idx=2; file_idx<ARGC; file_idx++) {
                printf "\t%s", reads[file_idx][line]
            }
            print ""
        }
    }' *.tsv > reads_table.tsv

注意事项

  • 必须确保所有TSV文件的name列顺序和内容完全一致,否则两种方法都会出现行不匹配的问题。
  • 如果文件名包含空格或特殊字符,务必用双引号包裹文件名变量(比如方法一中的"$f")。
  • 若不需要处理所有.tsv文件,可替换*.tsv为具体的文件名列表,比如sample1.tsv sample2.tsv ...。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 23:45:41