使用jq合并对象:按相同x值合并数组及处理gcloud快照数据
用JQ合并同键值对象的数组成员
基础示例:合并相同x值的y数组
假设你的输入JSON是:
[ {"x": "a", "y": [1,2]}, {"x": "b", "y": [3]}, {"x": "a", "y": [4,5]} ]
想要得到将相同x对应的y数组合并后的结果:
[ {"x": "a", "y": [1,2,4,5]}, {"x": "b", "y": [3]} ]
方法1:用group_by分组合并
这是最直观的方式:
group_by(.x) | map({x: .[0].x, y: map(.y[])})
group_by(.x):按x字段将数组分组,每组是相同x值的对象集合map(...):遍历每个分组,提取分组的x值(取第一个对象的x即可,因为分组内都是相同值),然后将所有对象的y数组成员展开合并成一个新数组
方法2:用reduce构建键值映射后转换
如果需要更灵活的控制,可以用reduce先构建以x为键的临时对象,再转成目标格式:
reduce .[] as $item ({}; .[$item.x] += {y: $item.y}) | to_entries | map({x: .key, y: .value.y})
reduce .[] as $item ({}; ...):遍历每个对象,初始值为空对象,将每个$item的y数组追加到对应x键的y字段中to_entries:将键值对象转成{key, value}格式的数组map(...):将键值结构转换回你需要的{x, y}对象格式
实际场景:合并GCloud Compute快照数据
针对gcloud compute snapshots返回的JSON数据,要将同一实例的快照合并到单个对象中,假设你的gcloud输出结构类似:
[ { "name": "snap-1", "sourceInstance": "instance-a", "creationTimestamp": "2024-01-01T00:00:00Z", "diskSizeGb": "10" }, { "name": "snap-2", "sourceInstance": "instance-a", "creationTimestamp": "2024-01-02T00:00:00Z", "diskSizeGb": "10" }, { "name": "snap-3", "sourceInstance": "instance-b", "creationTimestamp": "2024-01-03T00:00:00Z", "diskSizeGb": "20" } ]
目标是按sourceInstance分组,将同一实例的快照整理到一个数组中:
最终命令
gcloud compute snapshots list --format=json | jq ' group_by(.sourceInstance) | map({ instance: .[0].sourceInstance, snapshots: map(del(.sourceInstance)) }) '
group_by(.sourceInstance):按实例名分组所有快照map({instance: ..., snapshots: ...}):每个分组生成一个对象,instance字段取分组的实例名,snapshots字段是分组内所有快照对象(删除重复的sourceInstance字段)
如果需要保留实例的其他共性字段(比如磁盘大小),可以直接从第一个快照对象提取,比如:
group_by(.sourceInstance) | map({ instance: .[0].sourceInstance, diskSizeGb: .[0].diskSizeGb, snapshots: map({name, creationTimestamp}) })
内容的提问来源于stack exchange,提问作者sandboxcom
相关产品推荐
相关产品推荐

