Awk 对多个文件的非唯一行求和

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

我想合并(求和)每个文件中不唯一的所有行的值:我有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-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}' *