如何合并双行,将所有唯一数据保留在第2列中

时间:2019-02-18 17:39:55

标签: sorting unix awk

我正在尝试根据第1列中的标识符合并相同的行。第2列中的信息不一定相同。我如何融合双打以保留第二列的所有唯一记录?

数据前三行的示例:

>TRINITY_DN100377_c0_g1  GO:0046556,GO:0009044,GO:0045493,
>TRINITY_DN10038_c0_g1  GO:0005783,GO:0005789,GO:0016021,GO:0004581,
>TRINITY_DN10038_c0_g1   GO:0005789,GO:0004598

我想得到:

>TRINITY_DN100377_c0_g1  GO:0046556,GO:0009044,GO:0045493,
>TRINITY_DN10038_c0_g1  GO:0005783,GO:0005789,GO:0016021,GO:0004581,GO:0004598,

所以简单地将保险丝加倍,但保留第2列的所有唯一性。

我正在使用:

cat file | sort -u | awk '!seen[$1]++' > newfile

但这只会导致保留第一行双打,其余的将被删除。

有人可以帮助我,如何保留所有唯一的GO条款?

2 个答案:

答案 0 :(得分:2)

$ cat tst.awk
$1 != prev {
    printf "%s%s  ", (NR>1 ? ORS : ""), $1
    delete seen
    prev = $1
}
{
    n = split($2,tmp,/,/)
    for (i=1; i<=n; i++) {
        val = tmp[i]
        if ( (val != "") && !seen[val]++ ) {
           printf "%s,", val
        }
    }
}
END { print "" }
$
$ awk -f tst.awk file
>TRINITY_DN100377_c0_g1  GO:0046556,GO:0009044,GO:0045493,
>TRINITY_DN10038_c0_g1  GO:0005783,GO:0005789,GO:0016021,GO:0004581,GO:0004598,

答案 1 :(得分:1)

如果您不介意订单(GNU awk):

awk -F'[, ]*' '{for (i=2;i<=NF;i++) if($i!="")a[$1][$i]}END{for(k in a){printf "%s ", k; for(j in a[k]) printf "%s,", j;print ""}} ' file
>TRINITY_DN100377_c0_g1 GO:0046556,GO:0009044,GO:0045493,
>TRINITY_DN10038_c0_g1 GO:0004581,GO:0005783,GO:0004598,GO:0016021,GO:0005789,

如果要删除最后一个,

awk -F'[, ]*' '{for (i=2;i<=NF;i++) if($i!="")a[$1][$i]}END{for(k in a){e=sprintf("%s ", k); for(j in a[k]) e=e sprintf("%s,", j);sub(/.$/,"",e);print e}} ' file
>TRINITY_DN100377_c0_g1 GO:0046556,GO:0009044,GO:0045493
>TRINITY_DN10038_c0_g1 GO:0004581,GO:0005783,GO:0004598,GO:0016021,GO:0005789