合并由两列组成的文件

时间:2015-09-24 20:59:08

标签: perl awk

我有多个看起来像这样的文件:

文件1:

rsRNA-2312-n    2
rsRNA-6508-n    2
rsRNA-6382-n    10
rsRNA-951-n 0
rsRNA-6330-n    4
rsRNA-6330-n    11
rsRNA-1385-n    3
rsRNA-4945-n    0
rsRNA-946-n 9

file2的:

rsRNA-552-n 2
rsRNA-5301-n    7
rsRNA-6487-n    0
rsRNA-4945-n    7
rsRNA-2445-n    9
rsRNA-6490-n    2

file3的:

rsRNA-4946-n    1
rsRNA-5058-n    0
rsRNA-552-n 0
rsRNA-849-n 2
rsRNA-3302-n    2
rsRNA-4099-n    0
rsRNA-552-n 1

我想合并创建输出的文件,该输出在单独的列中包含每个输入文件的值,并在column1中合并唯一标识符(输入文件中的第1列)。如果在特定输入文件中找不到标识符,则此特定输入的此标识符的计数应为0。

输出(非真实数据):

identifier   file1   file2    file3
rsRNA-552-n 2    4    5
rsRNA-5301-n    7   12    2
rsRNA-6487-n    0    1    5
rsRNA-4945-n    7   12   1
rsRNA-2445-n    9   4    55
rsRNA-6490-n    2  1    0

正在尝试:

paste <(awk '{print $2}' file1 ) <(awk '{print $2}' file2 ) <(awk '{print $2}' file3) <(awk '{print $2}' file4)

并使用for循环:

for f in file*; do
base_name=${f%.txt}
id=${base_name#*_}
awk  > "output${id}"
done

2 个答案:

答案 0 :(得分:2)

使用shell循环来操作文本总是错误的方法。只需使用awk,它就是它的设计目标。使用GNU awk 4. *表示真正的多D数组和ARGIND并对in进行排序:

$ cat tst.awk
{
    split($1,a,/-/)
    key = a[2]
    key2name[key] = $1
    key2val[key][ARGIND] = $2
}
END {
    printf "identifier"
    for (fileNr=1;fileNr<=ARGIND;fileNr++) {
        printf "%s%s", OFS, ARGV[fileNr]
    }
    print ""

    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (key in key2name) {
        printf "%s", key2name[key]
        for (fileNr=1;fileNr<=ARGIND;fileNr++) {
            printf "%s%s", OFS, (fileNr in key2val[key] ? key2val[key][fileNr] : 0)
        }
        print ""
    }
}

$ awk -f tst.awk file1 file2 file3
identifier file1 file2 file3
rsRNA-552-n 0 2 1
rsRNA-849-n 0 0 2
rsRNA-946-n 9 0 0
rsRNA-951-n 0 0 0
rsRNA-1385-n 3 0 0
rsRNA-2312-n 2 0 0
rsRNA-2445-n 0 9 0
rsRNA-3302-n 0 0 2
rsRNA-4099-n 0 0 0
rsRNA-4945-n 0 7 0
rsRNA-4946-n 0 0 1
rsRNA-5058-n 0 0 0
rsRNA-5301-n 0 7 0
rsRNA-6330-n 11 0 0
rsRNA-6382-n 10 0 0
rsRNA-6487-n 0 0 0
rsRNA-6490-n 0 2 0
rsRNA-6508-n 2 0 0

我添加了key的轻微额外复杂性作为第一个字段的数字部分,因此在输出结果时,可以在该子字段上以数字方式对它们进行排序。

答案 1 :(得分:1)

另一种解决方案......

awk '
{ d[$1][FILENAME] = $2 }
END{
    line = "identifier";
    for (i=1; i in ARGV; i++) line = line OFS ARGV[i];
    print line
    for(i in d){
        line = i;
        for (j=1; j in ARGV; j++){
            if(ARGV[j] in d[i]) line = line OFS d[i][ARGV[j]]
            else line = line OFS 0
        }
        print line
    }
}' file1 file2 file3

你得到:

identifier file1 file2 file3
rsRNA-946-n 9 0 0
rsRNA-4945-n 0 7 0
rsRNA-1385-n 3 0 0
rsRNA-2312-n 2 0 0
rsRNA-6382-n 10 0 0
rsRNA-951-n 0 0 0
rsRNA-6490-n 0 2 0
rsRNA-6330-n 11 0 0
rsRNA-5301-n 0 7 0
rsRNA-5058-n 0 0 0
rsRNA-4946-n 0 0 1
rsRNA-2445-n 0 9 0
rsRNA-552-n 0 2 1
rsRNA-6487-n 0 0 0
rsRNA-4099-n 0 0 0
rsRNA-849-n 0 0 2
rsRNA-3302-n 0 0 2
rsRNA-6508-n 2 0 0