awk:计算不同文件中数据的平均值

awk: compute mean values for the data in distinct files

我正在使用 bash + awk 从目录中的日志文件中提取一些信息,并将摘要保存在单独的文件中。 在每个日志文件的底部,有一个 table 像:

mode |   affinity | dist from best mode
     | (kcal/mol) | rmsd l.b.| rmsd u.b.
-----+------------+----------+----------
   1       -6.961          0          0
   2       -6.797      2.908      4.673
   3       -6.639      27.93      30.19
   4       -6.204      2.949      6.422
   5       -6.111      24.92      28.55
   6       -6.058      2.836      7.608
   7       -5.986      6.448      10.53
   8        -5.95      19.32      23.99
   9       -5.927      27.63      30.04
  10       -5.916      27.17      31.29
  11       -5.895      25.88      30.23
  12       -5.835      26.24      30.36

由此我需要关注第二列中的(负)值。值得注意的是,我需要从第二列(从 -6.961 到 -5.916)中获取 10 个第一个值并计算它的平均值并将平均值与日志名称一起保存为新 ranking.log 中的一个字符串 所以对于 5 个处理过的日志,它应该是这样的:

# ranking_${output}.log
log_name1 -X.XXX
log_name2 -X.XXX
log_name3 -X.XXX
log_name4 -X.XXX
log_name5 -X.XXX

其中 -X.XXX 是为每个日志计算的前 10 个位置的平均值。

这是我在 bash 函数中集成的 awk 代码,它从每个日志中提取第一个值(示例 table 中的 -6.961 )(没有均值计算)。

 # take only the first line (lowest dG) from each log
take_the_first_value () {
    awk '=="1"{sub(/.*\//,"",FILENAME); sub(/\.log/,"",FILENAME); printf("%s: %s\n", FILENAME, )}' "${results}"/*.log  > "${results}"/ranking.csv
} 

我可以修改 AWK 部分以添加 MEAN 值的计算,而不是始终采用位于 table 的第一行的值吗?

我建议使用 GNU awk:

awk -v num=10 'BEGINFILE{ c=sum=0 }
     ~/^[0-9]+$/ && NF==4{
       c++; sum=sum+;
       if(c==num){
         sub(/.*\//, "", FILENAME);
         print FILENAME, sum/num
       }
     }' "${results}"/*.log  >> "${results}"/ranking.csv

我使用 ~/^[0-9]+$/ && NF==4 来识别正确的行。

这为您提供了平均值。用于查找第一个值的模式是行 ^---+--- 后跟下一行的第一个字段中的 [:digit:]。对于每个日志文件做

$ awk '~/[[:digit:]]/ && set==1{ x+=; i++;
    gsub(/\/*.*\//,"", FILENAME);               
    if(i==10){ set=0; print FILENAME, x/i; i=0; x=0 } } 
    /^\-+\+\-+/{ set=1 }' "${results}"/*.log > "${results}"/ranking.csv

对于 ENDFILE 使用 GNU awk:

$ cat tst.sh
#!/usr/bin/env bash

awk '
    (+0) < 0 {
        sum += 
        if ( ++cnt == 10 ) {
            nextfile
        }
    }
    ENDFILE {
        print FILENAME, (cnt ? sum/cnt : 0)
        cnt = sum = 0
    }
' "${@:--}"

$ ./tst.sh file
file -6.2549

请注意,即使您的输入文件末尾少于 10 行(包括空文件),上述方法也能正常工作。