列读取和平均值(BASH)

时间:2015-10-12 03:16:03

标签: bash

所以我正在处理列平均问题

我有几列数字,

1 2 3 4 5
2 3 4 5 6
8 4 5 6 7
9 8 7 6 5
1 9 9 9 2 

我想要做的是取每列的平均值,以便它们产生

4 5 5 6 5

求和部分不是问题,我能够得到每列的总和。但是,不知怎的,我在计算列数(变量$ x)时遇到了麻烦 这是我的代码

while read line; do
   x = 0
   read -a array <<< "$line"

    for i in "${!array[@]}"
    do
        column[${i}]=$((${column[${i}]}+${array[$i]}))
        ((x++))
    done
done < $TMP

for sum in ${column[@]}
do
    average=`expr $sum / $x`
    remainder=`expr $sum % $x`
    mult=`expr $remainder \* 10`
    fracvalue=`expr $mult / $x`
    echo $x
    echo $average
    echo $sum
    echo $remainder
    echo $mult
    echo $fracvalue
done

最后几行是我的测试目的,这里$ X一直显示1而不是5.这就是为什么它搞砸了所有其他变量。有谁知道这段代码中的缺陷在哪里?非常感谢您的帮助。感谢

4 个答案:

答案 0 :(得分:0)

问题在于 x = 0 应该 x=0并将((x+1))设为let "x+=1"它应该有效。

答案 1 :(得分:0)

另一种方法:

#!/bin/bash

declare -ia sum        # declare array of integers
declare -i lines=0     # declare integer to count lines

# read file to array and sum values
while read -ra array; do
  for ((i=0; i<${#array[@]};i++)); do 
    sum[$i]+=${array[$i]}
  done
  lines+=1
done < file

# print averages
for ((j=0; j<$i;j++)); do            
  echo -n "$((${sum[$j]}/$lines)) "
done

输出:

4 5 5 6 5 

答案 2 :(得分:0)

也许您的文件在每列中没有相同的行数。

while read line; do
   read -a array <<< "$line"

    for i in "${!array[@]}"
    do
      column[${i}]=$((${column[${i}]}+${array[$i]}))
      ((x[${i}]++))
    done
done < $TMP

for i in ${!column[@]}
do
    sum=${column[$i]}
    x=${x[${i}]}
    #your calcul
done

答案 3 :(得分:0)

除了一些语法特性之外,最初的问题是在每个x上重置read会导致您丢失行数。此外,您的阵列是索引数组,而不是关联数组。

在开头进行小调整并declare变量(提示bash它们是整数或数组),它按计划工作。 注意:不需要 here-string 来分配数组,只需使用常规数组语法。另请注意,对于索引数组,无需在[ ]内取消引用变量,只需${array[i]}即可。

虽然expr的使用很好(旧的,慢的,但是可移植且很好),但最后可以使用bash算法语法进行参数计算。 (你已经有了数组)。最后,您最好在第一个读取循环中初始化每个column[$i]=0。你可以用一个简单的标志来做到这一点:

#!/bin/bash

declare -i ncols=0
declare -i x=0
declare -a column

while read -r line; do

    array=( $line )
    [ $ncols -eq 0 ] && ncols=${#array[@]}

    for ((i = 0; i < ncols; i++))
    do
        [ $x -eq 0 ] && column[$i]=0
        column[$i]=$(( ${column[i]} + ${array[i]}))
    done

    ((x++))

done < "$1"

for sum in ${column[@]}
do
    average=`expr $sum / $x`
    remainder=`expr $sum % $x`
    mult=`expr $remainder \* 10`
    fracvalue=`expr $mult / $x`
    echo $x
    echo $average
    echo $sum
    echo $remainder
    echo $mult
    echo $fracvalue
done

exit 0

<强>输出

$ bash colavg.sh dat/colavg.txt
5
4
21
1
10
2
5
5
26
1
10
2
5
5
28
3
30
6
5
6
30
0
0
0
5
5
25
0
0
0