我该如何让 jq 处理这样的 JSON 数据:
{
"host1": { "ip": "10.1.2.3" },
"host2": { "ip": "10.1.2.2" },
"host3": { "ip": "10.1.18.1" }
}
生成以下输出:
host1, 10.1.2.3
host2, 10.1.2.2
host3, 10.1.18.1
我对格式不感兴趣,我只是弄不清楚如何访问键名和值。
要将顶层键作为流获取,可以使用内置函数 keys[]
。因此,解决您特定问题的一个方法是:
jq -r 'keys[] as $k | "\($k), \(.[$k] | .ip)"'
keys
以排序后的顺序返回键名;如果您想按原始顺序返回,则使用 keys_unsorted
。
另一种以原始顺序返回键的选择是:
jq -r 'to_entries[] | "\(.key), \(.value | .ip)"'
在这里也值得考虑使用@csv和@tsv过滤器,例如:
jq -r 'to_entries[] | [.key, .value.ip] | @tsv'
产生:
host1 10.1.2.3
host2 10.1.2.2
host3 10.1.18.1
如果需要的键被嵌套在一个对象中,如下所示的例子,那么 jq 过滤器就需要按照以下方式进行修改。
输入:
{
"myhosts": {
"host1": { "ip": "10.1.2.3" },
"host2": { "ip": "10.1.2.2" },
"host3": { "ip": "10.1.18.1" }
}
}
修改:
jq -r '.myhosts | keys[] as $k | "\($k), \(.[$k] | .ip)"'
发现了一种非常优雅的解决方案
jq 'with_entries(.value |= .ip)'
输出什么
{
"host1": "10.1.2.3",
"host2": "10.1.2.2",
"host3": "10.1.18.1"
}
这里是 jqplay 的测试代码片段:https://jqplay.org/s/Jb_fnBveMQ
with_entries
函数将列表中的每个对象转换为键值对,因此我们可以分别访问 .key
或 .value
,通过使用更新操作符 |=
,我们正在更新(覆盖)每个 KV 项的 .value
字段与 .ip
字段。
.["id address"]
,就像在正常情况下一样。 - peak