如何从 bash 中的 ASCII 文件数据计算平均值?

mcE*_*nge 7 command-line bash

在 bash 中,我可以从这样的日志文件中 grep 一些时间测量

grep "time:" myLogfile.txt | cut -d' ' -f 3 >> timeMeasurements.txt

#timeMeasurements.txt
2.5
3.5
2.0
...
Run Code Online (Sandbox Code Playgroud)

现在我想从timeMeasurements.txt. 在 bash 中最快的方法是什么?
我知道有 gnuplot 和 R,但似乎必须为它们中的任何一个编写一些冗长的脚本。

ste*_*ver 13

强制性GNU 数据混杂版本

$ datamash mean 1 < file
2.6666666666667
Run Code Online (Sandbox Code Playgroud)

旁白:感觉这真的应该可以在本机中实现bc(即不使用 shell 或外部程序来循环输入值)。GNUbc实现包括一个read()函数——但是让它检测输入结束似乎非常困难。我能想到的最好的方法是:

#!/usr/bin/bc

scale = 6
while( (x = read()) ) {
  s += x
  c += 1
}
s/c
quit
Run Code Online (Sandbox Code Playgroud)

然后你可以通过管道输入文件,只要你用任何非数字字符终止输入,例如

$ { cat file; echo '@'; } | ./mean.bc
2.666666
Run Code Online (Sandbox Code Playgroud)


Zan*_*nna 12

你可以使用awk. Bash 本身不是很擅长数学......

awk 'BEGIN { lines=0; total=0 } { lines++; total+=$1 } END { print total/lines }' timeMeasurements.txt
Run Code Online (Sandbox Code Playgroud)

笔记

  • lines=0; total=0 将变量设置为 0
  • lines++lines每行增加一个
  • total+=$1 将每行中的值添加到运行总数中
  • print total/lines 完成后,将总数除以值的数量

  • 尽管这是一个很好的做法,但变量实际上*不需要*在`awk`中初始化-因此您可以将其“打高尔夫球”到`awk '{total+=$1} END{print total/NR}'` (3认同)

Dig*_*uma 11

另一种方式,使用sedbc

sed 's/^/n+=1;x+=/;$ascale=1;x/n' timemeasurements.txt | bc
Run Code Online (Sandbox Code Playgroud)

sed 表达式将输入转换为如下形式:

n+=1;x+=2.5
n+=1;x+=3.5
n+=1;x+=2.0
scale=1;x/n
Run Code Online (Sandbox Code Playgroud)

这是通过管道bc逐行评估它的。


mur*_*uru 8

改编此 U&L 帖子中的 R 命令:

$ Rscript -e 'd<-scan("stdin", quiet=TRUE)' -e 'cat(mean(d), sep="\n")' < foo
2.666667
Run Code Online (Sandbox Code Playgroud)


Arr*_*cal 5

您可以bcwhile循环中使用基本计算器read

count=0; sum=0; while read -r num; do ((count++)); sum=$(echo "$sum + $num" | bc); done < timeMeasurement.txt; echo "scale=2; $sum / $count" | bc -l
Run Code Online (Sandbox Code Playgroud)

或更易读:

count=0
sum=0
while read -r num
do
  ((count++))
  sum=$(echo "$sum + $num" | bc)
done < timeMeasurement.txt
echo "scale=2; $sum / $count" | bc -l
Run Code Online (Sandbox Code Playgroud)

解释:

  • 首先,我们将值的计数和总和设置为变量 count 和 sum,值为 0。
  • 逐行读取文件,将行中的值设置为变量num。我们使用构造while read -r num; do ... ; done < timeMeasurements.txt来做到这一点。这意味着我们将为文件的每一行做一些事情。
  • 在 while 循环中,使用 bash 算术将每一行的 count 变量加一((count++))
  • 使用 bash 命令替换$(...)echo管道 tobc将文件这一行的 num 变量的值添加到所有先前行的 num 变量的总和中。bc用作 bash 不能很好地处理浮点运算。

此时循环结束,count 变量包含时间测量值的数量,sum 变量包含时间测量值的总和。

  • echo与我们的变量一起使用以创建传递给 的均值计算bc。该scale=2部分说明bc要显示多少有效数字。