我有一个数组trf
。要计算每个数组项中第二个元素的和。
数组内容示例
trf=( "2 13 144" "3 21 256" "5 34 389" )
这是当前的实现,但我觉得它不够健壮。例如,对于每个数组条目中任意数量的元素(但认为从一个数组元素到另一个数组元素都是常量),它会失败。
cnt=0
m=${#trf[@]}
while (( cnt < m )); do
while read -r one two three
do
sum+="$two"+
done <<< $(echo ${array[$count]})
let count=$count+1
done
sum+=0
result=`echo "$sum" | /usr/bin/bc -l`
你把事情弄得太复杂了。就像
#!/usr/bin/env bash
trf=( "2 13 144" "3 21 256" "5 34 389" )
declare -i sum=0 # Integer attribute; arithmetic evaluation happens when assigned
for (( n = 0; n < ${#trf[@]}; n++)); do
read -r _ val _ <<<"${trf[n]}"
sum+=$val
done
printf "%dn" "$sum"
在纯bash
,或只是使用awk
(这是方便的,如果你有浮点数在你的实际数据):
printf "%sn" "${trf[@]}" | awk '{ sum += $2 } END { print sum }'
您可以使用printf
打印整个数组,每行一个条目。在这样的输入上,一个循环(while read
)就足够了。您甚至可以使用cut
和tr
来构建bc
命令,从而完全跳过循环。echo 0
在那里,以便bc
可以处理空数组和tr
插入的尾随+
。
{ printf %s\n "${trf[@]}" | cut -d' ' -f2 | tr \n +; echo 0; } | bc -l
对于您的示例,这将生成打印68
(= 13+21+34+0)。
试试这个printf
+awk
组合:
$ printf '%sn' "${trf[@]}" | awk '{print $2}{a+=$2}END{print "sum:", a}'
13
21
34
sum: 68
哦,Shawn已经建议过了。然后加上loop:
$ for item in "${trf[@]}"; do
echo $item
done | awk '{print $2}{a+=$2}END{print "sum:", a}'
13
21
34
sum: 68
对于相对较小的数组,for/while
双循环应该是ok的;将最后的总和放在$result
变量中(如OP的代码中):
result=0
for element in "${trf[@]}"
do
while read -r a b c
do
((result+=b))
done <<< "${element}"
done
echo "${result}"
由此产生:
68
对于较大的数据集,我可能会选择仅awk
的解决方案之一(出于性能原因)。