awk计算多个文本文件中的字段平均值并合并为一个

时间:2016-10-05 13:38:59

标签: bash awk

我正在尝试计算目录中多个测试文件中$2的平均值,并将输出合并到一个tab-delimeted输出文件中。输出文件是两个字段,其中$1pref提取的文件名,$2" is the calculated average with one decimal, rounded up. There is also a header in the output示例in $ 1 and百分比{{ 1}} $ 2`。下面似乎很接近,但我缺少一些东西(将标题添加到输出,合并到一个制表符分隔文件,并舍入到3个小数位),我不知道该怎么做而没有得到所需的输出。谢谢你:)。

123_base.txt

in

456_base.txt

AASS     99.81
ABAT     100.00
ABCA10   0.0

所需的输出(制表符分隔)

ABL2     97.81
ABO  100.00
ACACA    99.82

Sample Percent
123    66.6
456    99.2

4 个答案:

答案 0 :(得分:5)

这个使用GNU awk,它提供了方便的BEGINFILEENDFILE事件:

gawk '
    BEGIN {print "Sample\tPercent"}
    BEGINFILE {sample = FILENAME; sub(/_.*/,"",sample); sum = n = 0}
    {sum += $2; n++}
    ENDFILE {printf "%s\t%.1f\n", sample, sum/n}
' 123_base.txt 456_base.txt 

如果您提供附带目录的模式,我会得到如下示例名称:

match(FILENAME, /^.*\/([^_]+)/, m); sample = m[1]

然后,是的,这没关系:gawk '...' /path/to/*_base.txt

并且在詹姆斯·布朗的回答的启发下,以零的方式窃取分裂:

ENDFILE {printf "%s\t%.1f\n", sample, n==0 ? 0 : sum/n}

答案 1 :(得分:3)

perl

$ perl -ane '
BEGIN{ print "Sample\tPercent\n" }
$c++; $sum += $F[1];
if(eof)
{
    ($pref) = $ARGV=~/(.*)_base/;
    printf "%s\t%.1f\n", $pref, $sum/$c;
    $c = 0; $sum = 0;
}' 123_base.txt 456_base.txt
Sample  Percent
123 66.6
456 99.2
  • 使用BEGIN
  • 打印标题
  • -a选项会将空格上的输入行拆分并保存到@F数组
  • 对于每一行,增加计数器并添加到sum变量
  • 如果检测到文件结尾eof,请以所需格式打印
  • $ARGV包含正在阅读的当前文件名


如果传递了文件名的完整路径,但只应使用文件名来获取pref,那么请使用此行代替

($pref) = $ARGV=~/.*\/\K(.*)_base/;

答案 2 :(得分:2)

另一个awk

$ awk -v OFS='\t' '{f=FILENAME;sub(/_.*/,"",f); 
                    a[f]+=$2; c[f]++} 
                END{print "Sample","Percent"; 
                    for(k in a) print k, sprintf("%.1f",a[k]/c[k])}' {123,456}_base.txt

Sample Percent
456 99.2
123 66.6

答案 3 :(得分:2)

在awk中。注意printf "%3.3s"在第3个字符后截断文件名:

$ cat ave.awk
BEGIN {print "Sample", "Percent"}                      # header
BEGINFILE {s=c=0}                                      # at the start of every file reset
{s+=$2; c++}                                           # sum and count hits
ENDFILE{if(c>0) printf "%3.3s%s%.1f\n", FILENAME, OFS, s/c} 
                                                       # above output if more than 0 lines

运行它:

$ touch empty_base.txt                                 # test for division by zero
$ awk -f ave.awk 123_base.txt 123_base.txt empty_base.txt
Sample Percent
123 66.6
456 99.2