合并 JSON 个文件并使用 JQ 重新计算百分比

Combine JSON files and recalculate percentages with JQ

我在 bash shell 脚本中使用 jq 每天处理 JSON 文件列表,将它们组合成一个新数组。组合它们后,我需要根据数组中每个对象的值重新计算值。这个新的 JSON 文件随后会在面向客户的分析 HTML 报告中使用。

我快要让它工作了,但不知道如何组合下面的 jq 个过滤器。

我可以在 过滤器 A 中创建一个重新计算的百分比数组,并且我可以在 中输出我期望的数组(减去新的百分比值) ]过滤器 B 但找不到将它们组合成 过滤器 C.

的方法

JQ游乐场URL:https://jqplay.org/#

JSON input (located on gist.github)

过滤器 A:

{"hits_percents": [(.[].hits.count / (group_by(.hits.count) | map(map(.hits.count))|add|add)*100)], "visitors_percents": [(.[].visitors.count / (group_by(.visitors.count) | map(map(.visitors.count))|add|add)*100)], "bytes_percents": [(.[].bytes.count / (group_by(.bytes.count) | map(map(.bytes.count))|add|add)*100)]}

输出A:

{
  "hits_percents": [
    1.2345679012345678,
    8.641975308641975,
    8.641975308641975,
    9.876543209876543,
    6.172839506172839,
    3.7037037037037033,
    1.2345679012345678,
    2.4691358024691357,
    58.0246913580247
  ],
  "visitors_percents": [
    4,
    28.000000000000004,
    28.000000000000004,
    8,
    4,
    8,
    4,
    8,
    8
  ],
  "bytes_percents": [
    0.31110007608374707,
    36.59886623706793,
    31.692110521802018,
    7.187835244744665,
    1.6285539319606,
    5.880482040688714,
    0.7481999111612437,
    0.6484148671259253,
    15.304437169365146
  ]
}

过滤器 B:

[.[] | { "hits": {"count": .hits.count, "percent": "TODO" }, "visitors": { "count": .visitors.count, "percent": "TODO"}, "bytes": {"count": .bytes.count, "percent": "TODO"}, "data": .data }]

Output B (located on gist)

过滤器 C:(过滤器 A + B)

????

Desired Output C

关于如何使用 jq 在 bash 脚本中获取 输出 C 的任何建议都很棒。我已经转动齿轮几个小时了,目前没有想法。


奖金问题:我怎样才能让 jq 将百分比的 2 位四舍五入?

我无法进行任何数学运算,而且他们的 Math documentation 太含糊,帮不上什么忙。

根据您的中间结果 "A" 和 "B"(在下面用 $a 和 $b 表示),以下过滤器会生成所需的答案。关键是 transpose:

($a | [.hits_percents, .visitors_percents, .bytes_percents] | transpose)
| . as $v
| reduce range(0; length) as $i
    ($b;
       .[$i].hits.percent = $v[$i][0] 
     | .[$i].visitors.percent = $v[$i][1]
     | .[$i].bytes.percent = $v[$i][2] )

可能有更好的方法来获得最终结果,但您问的是如何将两个中间结果合并....

奖金问题:

 # Round a (positive) percentage to two decimal places:
 def percent:
   ((1000 * .) | floor)
   | (. % 10) as $r
   | ((. / 10) | floor) as $answer
   | if $r > 4 then ($answer + 1) else $answer end
   | . / 100
   ;

这可以通过在转置后添加map(map(percent))来使用:

def percent:
  ((1000 * .) | floor)
  | (. % 10) as $r
  | ((. / 10) | floor) as $answer
  | if $r > 4 then ($answer + 1) else $answer end
  | . / 100;
($a | [.hits_percents, .visitors_percents, .bytes_percents] | transpose)
  | map(map(percent))
  | . as $v
  | reduce range(0; length) as $i
      ($b;
         .[$i].hits.percent = $v[$i][0] 
       | .[$i].visitors.percent = $v[$i][1]
       | .[$i].bytes.percent = $v[$i][2] )