合并 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 }]
过滤器 C:(过滤器 A + B)
????
关于如何使用 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] )
我在 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 }]
过滤器 C:(过滤器 A + B)
????
关于如何使用 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] )