如何将jq输出中的所有数字求和

时间:2018-08-28 20:14:01

标签: jq

我有此命令,我想对输出中的所有数字求和。

命令如下所示

$(hadoop fs -ls -R /reports/dt=2018-08-27 | grep _stats.json | awk '{print $NF}' | xargs hadoop fs -cat | jq '.duration')

因此,它将列出/reports/dt=2018-08-27中的所有文件夹,仅获取_stats.json,并将其从jq传递到hadoop -cat,并从.duration中获取json。最终我得到这样的结果。

1211789 1211789 373585 495379 1211789

但是我希望命令将所有这些数字加起来成为4504331

7 个答案:

答案 0 :(得分:14)

最简单的解决方案是add过滤器:

jq '[.duration] | add'

需要用[括起来的括号]用于求和,因为add是对 array 而不是流的值求和。 (对于流求和,您将需要更复杂的解决方案,例如使用reduce,如其他答案中所述。)


根据输入的确切格式,您可能需要进行一些预处理才能实现此目的。

例如输入Charles Duffy’s answer中的示例输入

  • 使用inputs(请注意,{j {1}}可以避免jq吞没输入的第一行):

    -n
  • 或草率(jq -n '[inputs.duration] | add' <<< "$sample_data" )并迭代(-s):

    .[]

答案 1 :(得分:5)

另一种方法(即使并非所有持续时间都为整数,该方法也可以使用)是使您的jq代码起作用:

sample_data='{"duration": 1211789}
{"duration": 1211789}
{"duration": 373585}
{"duration": 495379}
{"duration": 1211789}'

jq -n '[inputs | .duration] | reduce .[] as $num (0; .+$num)' <<<"$sample_data"

...正确发出作为输出:

4504331

根据需要在标准输入上用管道替换<<<"$sample_data"

答案 2 :(得分:2)

您现在就可以使用add

jq '.duration | add'

答案 3 :(得分:1)

awk来营救!

$ ... | awk '{sum+=$0} END{print sum}'

4504331

答案 4 :(得分:1)

为了清楚和通用起见,可能值得定义sigma(s)以添加数字流:

... | jq -n '
  def sigma(s): reduce s as $x(0;.+$x); 
  sigma(inputs | .duration)'

答案 5 :(得分:0)

使用for循环。

total=0
for num in $(hadoop fs -ls -R /reports/dt=2018-08-27 | grep _stats.json | awk '{print $NF}' | xargs hadoop fs -cat | jq '.duration')
do
    ((total += num))
done
echo $total

答案 6 :(得分:0)

结合其他答案。

$ jq -n '[inputs | .duration] | add' <<< "$sample_data"

# 4504331

在用[inputs | .duration]求和之前,我必须格式化数组add中的值。