使用 bash 取一行和文件中所有行的所有数字的平均值

Using bash to take the average of all numbers on a line and all lines in a file

本质上,我有一个几千行的txt文件,每行包含300个数字。我需要取每行 300 个数字的平均值,然后取文件中所有平均值的平均值,a la;

0.4,0.5,0.6,0.7...
0.5,0.6,0.7,0.8...
0.6,0.7,0.8,0.9...

to

0.55
0.65
0.75

to

0.65

我已经尝试了一些我在网上找到的 bash 脚本,但它们都涉及查找列的平均值,而不是整个行的平均值。我目前的策略是使用两个脚本来执行此操作,一个用于查找每行的平均值,第二个用于查找所有行的平均值,但我一直无法弄清楚任何事情。我对 bash 和 UNIX 命令还是比较陌生,所以解决方案可能很明显,但我还没有找到它。

这是你可以做的,用简单的算术和 for 循环:

#!/bin/bash

data=$(cat data.txt) # Your primary data
all=0
l=0

for i in $data; do
    line=0
    k=0
    oldIFS=$IFS
    IFS=','
    for j in $i; do
        line=$(echo "scale=2; ($line+$j)" | bc)
        ((k++))
    done
    IFS=$oldIFS
    line=$(echo "scale=2; $line/$k" | bc)
    echo "Line $l: $line"
    all=$(echo "scale=2; ($all+$line)" | bc)
    ((l++))
done
all=$(echo "scale=2; $all/$l" | bc)
echo "Final result: $all"

结果:

Line 0: .55
Line 1: .65
Line 2: .75
Final result: .65

注意这里的IFS变量,用于改变for循环中的分隔符:https://bash.cyberciti.biz/guide/$IFS

Bash 是 shell 用于 high-level 任务,不是典型编程、读取文件和做算术的最佳选择。 awk 是此任务的标准 bash 工具。这是一个脚本:

> cat tst.awk
BEGIN { FS = "," }

{
    sum = 0
    for (i=1;i<=NF;i++) sum += $i
    avg = sum / NF
    total += avg
    print "Line " NR ": " avg
}

END { print "Lines average: " total/NR }

用法和输出:

> awk -f tst.awk file
Line 1: 0.55
Line 2: 0.65
Line 3: 0.75
Lines average: 0.65

FS 是要使用的字段分隔符。 BEGIN {} 部分在读取第一行之前执行。 awk 正在逐行读取文件,并且对于每个输入行,主体 {} 都会被执行。里面的代码是 self-explanatory 并且与标准编程语言非常相似。到达文件末尾后,执行 END {}