从数组条目中计算特定字段的总和
Computing sum of specific field from array entries
我有一个数组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 "%d\n" "$sum"
在纯 bash
中,或者只使用 awk
(如果你的真实数据中有浮点数,这很方便):
printf "%s\n" "${trf[@]}" | awk '{ sum += } 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 '%s\n' "${trf[@]}" | awk '{print }{a+=}END{print "sum:", a}'
13
21
34
sum: 68
哦,Shawn 已经建议了。然后循环:
$ for item in "${trf[@]}"; do
echo $item
done | awk '{print }{a+=}END{print "sum:", a}'
13
21
34
sum: 68
对于相对较小的数组,for/while
双循环应该没问题 re: 性能;将最终总和放在 $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
的解决方案之一(出于性能原因)。
我有一个数组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 "%d\n" "$sum"
在纯 bash
中,或者只使用 awk
(如果你的真实数据中有浮点数,这很方便):
printf "%s\n" "${trf[@]}" | awk '{ sum += } 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 '%s\n' "${trf[@]}" | awk '{print }{a+=}END{print "sum:", a}'
13
21
34
sum: 68
哦,Shawn 已经建议了。然后循环:
$ for item in "${trf[@]}"; do
echo $item
done | awk '{print }{a+=}END{print "sum:", a}'
13
21
34
sum: 68
对于相对较小的数组,for/while
双循环应该没问题 re: 性能;将最终总和放在 $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
的解决方案之一(出于性能原因)。