输出平均值的 Shell 程序

输出平均值的 Shell 程序

我需要做的是编写一个名为 avgs 的 shell 程序,该程序将从文件中读取包含数据的行,其中标题行可以位于数据中的任何行。

我必须对最后两列的每一列进行总计和计数,并且不得在总计和计数中包含第一行的数据。

这是包含数据的文件:

92876035 SMITZ  S 15 26
95908659 CHIANG R 10 29
SID      LNAME  I T1/20 T2/30
92735481 BRUCE. R 16 28
93276645  YU    C 17 27
91234987 MYRTH  R 15 16

shell 程序将向标准输出写入以下行:“平均值为 17 和 24”

这是我尝试过的,但它不起作用

count_ppl=0
total=0
while read ?? ?!
do
    total=$((sum+b))
    count_ppl=$((count_ppl+1))
done < filename
avg=$(echo "scale=2;$total/$count_ppl" | bc)
echo "The averages are = $avg"

这 ”??”和 ”?!”在“阅读时”旁边有吗,因为我不知道该放什么。

我想这可能会计算一列的一个平均值,但是我如何从列中获取数据并计算两个平均值。

(顺便说一句,这是 bash)。

答案1

不确定“并且不得将第一行的数据包含在总计和计数中”是什么意思。您的意思是必须排除行“92876035 SMITZ S 15 26”,或者只是不“求和”“SID LNAME I T1/20 T2/30”?

??需要?!替换为您需要的变量名称。最后提到的变量名称将保留输入的其余部分。您需要最后两列,因此在您的情况下有 5 列,语句while read可以是:

while read col1 col2 col3 col4 col5

接下来您需要检查该行是否是标题行。在本例中,我将测试第一列中的单词 SID:

if [ "$col1" != 'SID' ]

从这里我们可以开始计算:

totallines=$((totallines+1))
sumcol4=$((sumcol4+col4))
sumcol5=$((sumcol5+col5))

最后你可以使用以下方法计算平均值

avgcol4=$(echo "scale=2; $sumcol4/$totallines"|bc)
avgcol5=$(echo "scale=2; $sumcol5/$totallines"|bc)

要结束它,您可以使用以下脚本:

#!/bin/bash
while read col1 col2 col3 col4 col5
do
  if [ "$col1" != 'SID' ]
  then
      totallines=$((totallines+1))
      sumcol4=$((sumcol4+col4))
      sumcol5=$((sumcol5+col5))
  fi
done < /path/to/inputfile
avgcol4=$(echo "scale=2; $sumcol4/$totallines"|bc)
avgcol5=$(echo "scale=2; $sumcol5/$totallines"|bc)
printf "The averages are %s and %s" $avgcol4 $avgcol5

另一种方法是使用awk

awk '{ if ( $1 != "SID" ) { COL4+=$4; COL5+=$5; } } END { LINES=NR-1; printf "The averages are %.2f and %.2f\n", COL4/LINES, COL5/LINES }' < /path/to/inputfile

上面的命令过滤标题行,否则对第 4 列和第 5 列求和,处理输入文件后,它将把 LINES 变量设置为记录数减 1(标题行)并打印输出行。

bash和版本awk都会输出:

The averages are 14.60 and 25.20

答案2

#!/usr/bin/awk -f

NR == 1     { next }
/^[^0-9]/   { next }

{
    s1 += $(NF - 1)
    s2 += $NF
    ++n;
}

END {
    printf("The averages are %.2f and %.2f\n", s1/n, s2/n)
}

测试:

$ chmod +x avgs
$ ./avgs file
The averages are 14.50 and 25.00

这用于awk跳过第一行数据(按照问题中的要求)以及包含非数字作为第一个字符的任何行。

对于所有其他行,它将最后两个字段的数字添加到 twe sums1s2,并且还递增计数器n

最后,打印结果,保留两位小数。

作为 shell 中的“一行”:

$ awk 'NR==1||/^[^0-9]/{next} {s1+=$(NF-1);s2+=$NF;++n} END {printf("The averages are %.2f and %.2f\n", s1/n, s2/n)}' file
The averages are 14.50 and 25.00

有关的:

相关内容