Awk 对多个文件的非唯一行求和
我想合并(求和)每个文件中不唯一的所有行的值:我有96个文件。我试着:Awk 对多个文件的非唯一行求和,awk,Awk,我想合并(求和)每个文件中不唯一的所有行的值:我有96个文件。我试着: for f in file* do awk '{a[$1]+=$2}END{for(i in a){print i, a[i]}}' "$f" > "out${f#merge}" done 文件1: rsRNA-8458-n 3 rsRNA-849-n 0 rsRNA-8617-n 0 rsRNA-946-n 0 rsRNA-9538-n 1 rsRNA-9811-n 1 rsRNA-9811
for f in file*
do
awk '{a[$1]+=$2}END{for(i in a){print i, a[i]}}' "$f" > "out${f#merge}"
done
文件1:
rsRNA-8458-n 3
rsRNA-849-n 0
rsRNA-8617-n 0
rsRNA-946-n 0
rsRNA-9538-n 1
rsRNA-9811-n 1
rsRNA-9811-n 3
rsRNA-9815-n 0
文件2
您的脚本当前将向每个文件写入唯一的总和,并将每个总和输出到一个文件,如
outfile1
。因为你在问一个关于它的问题,我假设你想对所有文件求和。下面是一个GNU awk脚本,它将对每个文件(默认)或所有文件的唯一条目求和,并根据数组a
中使用的索引字符串对输出进行排序:
#!/usr/bin/gawk -f
BEGIN { PROCINFO["sorted_in"] = "@ind_str_asc" }
lf != FILENAME {
if( !merge ) {
output()
delete( a )
}
lf = FILENAME
}
{ a[$1]+=$2 }
END { output() }
function output() {
fname = "out" (!merge ? lf : "")
for(k in a) {
print k, a[k] > fname
}
}
如果将其放入名为merge.awk
的文件中并使其可执行,则可以像以下方式运行它:
./merge.awk file*
这将创建与您现在获得的outfile1
,outfile2
文件相同的类型(尽管已排序)。相反,如果使用-v
标志使用真实值初始化merge
,如下所示:
./merge.awk -v merge=true file
将所有输入文件读入同一数组a
后,所有输出将进入一个名为out
的文件
以下是一个注释版本:
#!/usr/bin/gawk -f
BEGIN { PROCINFO["sorted_in"] = "@ind_str_asc" } # GNU array sorting
lf != FILENAME { # when the FILENAME changes
if( !merge ) { # output array a when merge variable is unset
output() # (which is the default for awk variables)
delete( a ) # delete the array after output() to reset
}
lf = FILENAME # track the last filename in lf
}
{ a[$1]+=$2 } # sum values of the same key in array a
END { output() } # output the contents of a
function output() { # define function output()
fname = "out" (!merge ? lf : "") # adjust the fname when merging
for(k in a) { # sorted in gawk via PROCINFO
print k, a[k] > fname # write the contents of array a
}
}
如果您只希望合并所有文件,您可以更简单地执行以下操作:
awk '{a[$1]+=$2}END{for(i in a){print i, a[i]}}' file* > out
然后附加
| sort
对它们进行排序。不清楚在每个文件中不是唯一的所有行的含义,但是假设您的awk脚本对一个文件执行您想要的操作-同样,您不需要shell循环,只需让awk一次处理所有文件即可
使用GNU awk作为结束文件:
awk '{a[$1]+=$2} ENDFILE{for(i in a) print i, a[i] > (FILENAME".out"); delete a}' *
如果这不是您想要的,请编辑您的问题,以澄清并提供您发布的2个输入文件的预期输出。我觉得不错;有什么问题吗?
awk '{a[$1]+=$2} ENDFILE{for(i in a) print i, a[i] > (FILENAME".out"); delete a}' *