我正在尝试根据第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条款?
答案 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