我在一个只有两列的目录中有很多(几十个)TSV文件,我想根据第一列的值合并所有的TSV文件(两列都有我需要维护的标题);如果这个值存在,那么它必须加上相应的第二列的值,依此类推(见示例)。2文件可能有不同的行数,并且不按第一列排序,尽管这可以很容易地通过排序来完成。
我试过join,但是只对两个文件有效。join可以扩展到一个目录中的所有文件吗?我认为awk可能是一个更好的解决方案,但是我对awk的了解非常非常有限。有什么想法吗?
下面是三个文件的示例:
S01.tsv
Accesion S01
AJ863320 1
AM930424 1
AY664038 2
S02.tsv
Accesion S02
AJ863320 2
AM930424 1
EU236327 1
EU434346 2
S03.tsv
Accesion S03
AJ863320 5
EU236327 2
EU434346 2
输出文件应为:
Accesion S01 S02 S03
AJ863320 1 2 5
AM930424 1 1
AY664038 2
EU236327 1 2
EU434346 2 2
好的,感谢James Brown,我让这段代码正常工作(我将其命名为compile.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
当我用实际文件运行它时
awk -f compile.awk 01.tsv 02.tsv 03.tsv
输出如下:
LN854586.1.1236 1
JF128382.1.1303 1
Accesion S01 S02 S03
JN233077.1.1420 1
HQ836180.1.1388 1
KP718814.1.1338 1
JQ781640.1.1200 2
前两行不属于那里,因为文件应该以所有文件的标题(第三行)开始。有什么想法如何解决这个问题吗?
3条答案
按热度按时间pftdvrlh1#
我可能会这样处理它:
给定您的输入(排除调试),将打印:
sq1bmfud2#
这里有一个更简单的解决方案,使用eBay的tsv-utils,特别是tsv-join命令,如下所示:
只需要非常基本的攻击技巧。
bmp9r5qi3#
我使用
csvtool
来完成这个任务和许多csv/tsv任务(请参阅doc)。COMPARED
和COPIED
参数可以是单个数字、数字范围或逗号分隔的数字列表。-u TAB
和-t TAB
参数分别告诉csvtool
使用TAB作为输入和输出的分隔符。