Bash循环,用于计算列的总和

时间:2017-01-19 22:26:23

标签: bash

我正在尝试在Bash中编写一个循环,用于打印文件中每列的总和。这些列由制表符分隔。到目前为止我所拥有的是:

cols() {
  count=$(grep -c $'\t' $1)
  for n in $(seq 1 $count) ;do
    cat $FILE | awk '{sum+=$1} END{print "sum=",sum}'
  done
}

但这仅打印出第一列的总和。我怎样才能为每一栏做到这一点?

2 个答案:

答案 0 :(得分:3)

你的方法完成了这项工作,但它有点过分:你在计算列数,然后cat ting文件并调用awk,而awk单独可以完成所有操作它:

awk -F"\t" '{for(i=1; i<=NF; i++) sum[i]+=$i} END {for (i in sum) print i, sum[i]}' file

这利用NF来存储一行的字段数(这是你用count=$(grep -c $'\t' $1)做的事情)。然后,只需循环遍历字段并求和数组上的每个元素,其中sum[i]包含列i的总和。最后,它遍历结果并写入其值。

为什么你的方法不是给定一列的总和?因为当你说:

for n in $(seq 1 $count) ;do
    cat $FILE | awk '{sum+=$1} END{print "sum=",sum}'
done

您始终使用$1作为要求的元素。相反,您应该使用以下内容将值$n传递给awk:

awk -v col="$n" '{sum+=$col} END{print "sum=",sum}' $FILE # no need to cat $FILE

答案 1 :(得分:0)

如果你想要一个只有bash内置的解决方案,这将有效:

declare -i i l
declare -ai la sa=()
while read -d$'\t' -ra la; do
    for ((l=${#la[@]}, i=0; i<l; sa[i]+=la[i], ++i)); do :; done
done < file
(IFS=$'\t'; echo "${sa[*]}")

这个性能应该不错,但比awk更慢。