我正在尝试在Bash中编写一个循环,用于打印文件中每列的总和。这些列由制表符分隔。到目前为止我所拥有的是:
cols() {
count=$(grep -c $'\t' $1)
for n in $(seq 1 $count) ;do
cat $FILE | awk '{sum+=$1} END{print "sum=",sum}'
done
}
但这仅打印出第一列的总和。我怎样才能为每一栏做到这一点?
答案 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更慢。