【问题标题】:Combine JSON files and recalculate percentages with JQ合并 JSON 文件并使用 JQ 重新计算百分比
【发布时间】:2017-05-14 09:15:11
【问题描述】:

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

我非常接近让它工作,但不知道如何组合我下面的jq 过滤器。

我可以在 Filter A 中创建一个重新计算的百分比数组,并且我可以在 Filter B 中输出我期望的数组(减去新的百分比值)但找不到将这些组合成Filter C的方法。

JQ 游乐场网址: 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 太模糊,无法提供帮助。

【问题讨论】:

    标签: arrays json bash unix jq


    【解决方案1】:

    就您的中间结果“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] )
    

    【讨论】:

    • 太棒了,这看起来很有前途@peak!我一直试图让它工作大约一个小时并不断收到error: transpose is not defined。有什么想法可能导致这种情况吗? (我在 bash 而不是 jq play 网站上这样做,因为我也无法在该网站上运行它)
    • transpose 作为 jq 1.5 的内置函数包含在内。如果您无法获得带有transpose 的 jq 版本,那么您可以粘贴其定义。例如来自github.com/stedolan/jq/blob/master/src/builtin.jq
    • 有道理,我使用的是 jq v1.3。我会更新并再试一次。感谢您的快速响应!
    • 我安装了 v1.5,经过大量试验和错误后,我无法在我的 bashjq play 站点上使其在本地工作。我会完全责备自己不知道如何实施您的解决方案。您能否提供更多关于我如何使用您的答案创建jq '...' 命令行输出的信息(在jq play 或我的bash 上工作)?
    • 首先,我暂时忘记海绵。其次,我建议将“A 输出”放入名为(类似)a.json 的文件中,将“B 输出”放入名为(例如)b.json 的文件中,然后按如下方式调用 jq:jq - n --argfile a a.json --argfile b b.json -f command.jq # 其中 command.jq 包含上面给出的程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    相关资源
    最近更新 更多