【问题标题】:Computing sum of specific field from array entries从数组条目计算特定字段的总和
【发布时间】:2021-09-06 19:01:13
【问题描述】:

我有一个数组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`

【问题讨论】:

  • 请将该示例输入的所需输出(无描述、无图像、无链接)添加到您的问题(无评论)。

标签: arrays bash field


【解决方案1】:

你把它弄得太复杂了。类似的东西

#!/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 += $2 } END { print sum }'

【讨论】:

  • 或者如果你可以安装 GNU datamash,printf "%s\n" "${trf[@]}" | datamash -W sum 2
  • 我喜欢浮点计算的能力。
  • 如何修改awk 命令,以便从外部变量中获取字段编号?
  • @Angio awk -v f=2 '{ sum += $f } END { print sum }'
【解决方案2】:

您可以使用printf 打印整个数组,每行一个条目。对于这样的输入,一个循环 (while read) 就足够了。您甚至可以使用cuttr 完全跳过循环来构建bc 命令。 echo 0 在那里,以便bc 可以处理空数组和tr 插入的尾随+

{ printf %s\\n "${trf[@]}" | cut -d' ' -f2 | tr \\n +; echo 0; } | bc -l

对于您的示例,这会生成打印 68 (= 13+21+34+0)。

【讨论】:

    【解决方案3】:

    试试这个printf + awk 组合:

    $ printf '%s\n' "${trf[@]}" | awk '{print $2}{a+=$2}END{print "sum:", a}'
    13
    21
    34
    sum: 68
    

    哦,Shawn 已经建议过了。然后循环:

    $ for item in "${trf[@]}"; do
        echo $item
    done | awk '{print $2}{a+=$2}END{print "sum:", a}'
    13
    21
    34
    sum: 68
    

    【讨论】:

      【解决方案4】:

      对于相对较小的数组,for/while 双循环应该没问题 re: performance;将最终总和放在$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-only 解决方案之一(出于性能原因)。

      【讨论】:

      • 为什么需要while 循环?这可以通过read -r a b c &lt;&lt;&lt; "${element}" 完成
      猜你喜欢
      • 2017-07-21
      • 2018-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      相关资源
      最近更新 更多