根据每行上的实例数计算平均值 - Bash - AWK

Calculate average depending on number of instances on each line - Bash - AWK

当每行的字母数字实例数量(包括最终总平均值)有变化时,如何计算每行的平均值?

即。 pie.txt:

0.8pie 0.7pie 0.6pie            
34.2pie 34.1pie 35.8pie 
42pie 43pie 43pie
44pie 41pie 38pie
0.8pie
34.2pie 34.1pie
42pie 43pie 43.0pie
44.1pie 41pie 38.7pie 58.2pie

期望的输出:

Instances of Pie:               Avg:
0.8pie 0.7pie 0.6pie            Avg pie:  0.7pie
34.2pie 34.1pie 35.8pie         Avg pie:  34.7pie
42pie 43pie 43pie               Avg pie:  42.7pie
44pie 41pie 38pie               Avg pie:  41pie
0.8pie                          Avg pie:  0.8pie
34.2pie 34.1pie                 Avg pie:  34.15pie
42pie 43pie 43.0pie             Avg pie:  42.7pie
44.1pie 41pie 38.7pie 58.2pie   Avg pie:  45.5pie

Total Average:                            30.28pie

如果每行总是有一个固定的数量,比如 2 个或者说 3 个馅饼,那么是的,我可以轻松利用 awk print (++)/3 等。但是当每行有差异时,我会很挣扎。

我会想象使用条件语句来确定每一行的数字。 IE。如果第一行有 3,则除以 3,如果第二行有 4,则除以 4,依此类推

有好心人帮忙吗?

您可以使用这个 awk:

awk 'function prt(s1, s2) {printf "%-40s %s\n", s1, s2} NR==1 {prt("Instances of Pie:", "Avg:")} NF {s=0; for (i=1; i<=NF; ++i) s+=$i; avg=s/NF; ++rec; sum+=avg; prt([=10=], "Avg pie:  " avg "pie")} !NF; END {prt("\nTotal Average:", sum/rec "pie")}' file

Instances of Pie:                        Avg:
0.8pie 0.7pie 0.6pie                     Avg pie:  0.7pie
34.2pie 34.1pie 35.8pie                  Avg pie:  34.7pie
42pie 43pie 43pie                        Avg pie:  42.6667pie
44pie 41pie 38pie                        Avg pie:  41pie
0.8pie                                   Avg pie:  0.8pie
34.2pie 34.1pie                          Avg pie:  34.15pie
42pie 43pie 43.0pie                      Avg pie:  42.6667pie
44.1pie 41pie 38.7pie 58.2pie            Avg pie:  45.5pie

Total Average:                           30.2729pie

更易读的形式:

awk '
function prt(s1, s2) {
   printf "%-40s %s\n", s1, s2
}
NR == 1 {
   prt("Instances of Pie:", "Avg:")
}
NF {
   s = 0
   for (i=1; i<=NF; ++i)
      s += $i
   avg = s/NF
   prt([=11=], "Avg pie:  " avg "pie")
   ++rec
   sum += avg
}
!NF
END {
   prt("\nTotal Average:", sum/rec "pie")
}' file

Perl,但它确实比 anubhava 的回答没有优势

perl -MList::Util=sum,max -lane '
      sub avg {sum(@_) / @_}
      push @lines, $_;
      push @avg, avg(@F);
  } END {
      $maxl = max map {length} @lines;
      printf "%-*s Avg:\n", $maxl, "Instances of Pie:";
      printf "%-*s Avg pie: %.1fpie\n", $maxl, $lines[$_] , $avg[$_]
          for 0..$#lines;
      printf "\n%-*s          %.2fpie\n", $maxl, "Total Average:", avg(@avg);
' pie.txt