我在bash shell脚本中使用jq
每天处理一个JSON文件列表,将它们组合成一个新数组。在我将它们组合后,我需要根据数组中每个对象的值重新计算值。然后,这个新的JSON文件将在面向客户端的分析HTML报告中使用。
我非常接近它的工作,但无法弄清楚如何合并我的jq
过滤器。
我可以在过滤器A 中创建一个重新计算的百分比数组,然后我可以在过滤器B 中输出我期望的数组(减去新的百分比值)但无法找到将这些组合成过滤器C 的方法。
JQ Playground网址: 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 }]
过滤器C:(过滤器A + B)
????
有关如何使用jq
在bash脚本中获取输出C 的任何建议都会非常棒。我一直在调整我的齿轮几个小时,目前没有想法。
奖金问题:如何让jq
在百分比上舍入2位数?
我无法进行任何数学运算,他们的Math documentation太模糊,无法提供帮助。
答案 0 :(得分:3)
就您的中间结果“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] )