【发布时间】:2016-11-28 16:12:59
【问题描述】:
我在一个只有两列的目录中有许多(几十个)TSV 文件,我想根据第一列的值合并所有文件(两列都有我需要维护的标题);如果存在此值,则它必须添加相应的第二列的值,依此类推(参见示例)。文件可能有不同的行数并且不按第一列排序,尽管这可以通过排序轻松完成。
我尝试过 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
前两行不属于那里,因为文件应该以所有文件的标题(第三行)开头。 任何想法如何解决这个问题?
【问题讨论】:
-
您能否展示(在问题中)您到目前为止所尝试的内容?
-
基本上加入,尝试了一些 grep,并大量搜索类似的东西,但没有什么我可以实现或修改的,可能是因为我缺乏编码知识。加入正是我想要的,但只适用于两个文件。
-
您可以使用以下链接中的
program.awk。根据您的需要修改OFS(我假设是OFS="\t")。此外,输出记录顺序是随机的。 stackoverflow.com/questions/40373180/… -
加入 3 个文件
join -a 1 -a 2 -e "" -o 0,1.2,2.2 S01.tsv S02.tsv | join -a 1 -a 2 -e "" -o 0,1.2,1.3,2.2 - S03.tsv..... view join-multiple-files -
不按顺序输出,需要使用
sort输出或控制for的扫描,见here。awk -f compile.awk S*.tsv | sort。另外,如果你的第一个字段很长,标签不会这样做,你需要printf。