我尝试合并不同的JSON文件,其中包含以下类型的数据:
#file1:
{
"user1": {
"server1": 7.2,
"server2": 10.3
},
"user2": {
"server1": 15
}
}
#file2:
{
"user1": {
"server1": 8.5,
"server3": 20.5
},
"user3": {
"server1": 28
}
}
依此类推(每小时12个(。
这些数据是以百分比表示的服务器使用率的用户列表,每5分钟演变一次(根据资源使用情况,用户可能会消失和重新出现(。
我在Linux下,使用jq
等不同的Shell工具生成这些文件。
我的目标是每小时获得一个合并文件,所有可用数据的平均负载,就像这样(只考虑上面的2个文件(:
#result:
{
"user1": {
"server1": 7.85,
"server2": 5.15,
"server3": 10.25
},
"user2": {
"server1": 7.5
},
"user3": {
"server1": 14
}
}
我用reduce
命令尝试了几个查询,但都没有按预期工作。
也许最好的方法应该是解析每个文件,提取数据并将用户存储在不同的文件中,然后合并所有数据?
感谢您的分析和举例。
这里有一个用于任意数量输入文件的解决方案。它首先将每个值除以输入文件的数量,然后将它们相加,保留密钥:
jq -s '
.[][][] /= length
| reduce (.[] | to_entries[]) as $u ({};
reduce ($u.value | to_entries[]) as $s (.;
.[$u.key][$s.key] += $s.value
)
)
' file*
{
"user1": {
"server1": 7.85,
"server2": 5.15,
"server3": 10.25
},
"user2": {
"server1": 7.5
},
"user3": {
"server1": 14
}
}
演示
除法也可以通过在开头使用变量而转换为加法:
jq -s '
length as $c
| reduce (.[] | to_entries[]) as $u ({};
reduce ($u.value | to_entries[]) as $s (.;
.[$u.key][$s.key] += $s.value / $c
)
)
' file*
演示
一种方法:
jq -n
--argjson d1 file1.json
--argjson d2 file2.json
'
$d1 * $d2 |
with_entries(
.key as $user |
.value = (
with_entries(
.key as $server |
.value | ( $d1[ $user ][ $server ] + $d2[ $user ][ $server ] ) / 2
)
)
)
'
jqplay 演示
$d1 * $d2
创建了正确的结构,但使用了错误的值。然后我们修正价值。
另一种方法:
jq -s '
length as $n |
reduce ( .[] | to_entries[] ) as $_ ( { };
$_.key as $user |
reduce ( $_.value | to_entries[] ) as $_ ( .;
$_.key as $server |
.[ $user ][ $server ] += $_.value / $n
)
)
' file1.json file2.json
jqplay 演示
这个可以处理两个以上的文件!