jq:打印对象中每个条目的键和值


77

我如何让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

我对格式不感兴趣,只是无法弄清楚如何访问键名和值。

Answers:


120

要将顶级键作为流获取,可以使用内置函数 keys[]。因此,针对您的特定问题的一种解决方案是:

jq -r 'keys[] as $k | "\($k), \(.[$k] | .ip)"' 

keys按排序顺序生成键名;如果要按原始顺序使用它们,请使用keys_unsorted

另一种以原始顺序生成密钥的替代方法是:

jq -r 'to_entries[] | "\(.key), \(.value | .ip)"'

CSV和TSV输出

@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)"'

假设“ .ip”键中包含空格,例如“ ip address”,假设这是合理的话,那么如何将键周围的引号转义(假设您位于带引号的字符串的第三层)?
Saichovsky

1
是的,这是有道理的,这是一个很好的问题,但是请原谅我说,您可以轻松地自己回答,因为答案只是忽略了潜在的并发症。也就是说,通常的方法是引用带空格的字符串等。
高峰

我尝试过但没有成功。尝试将引号转义,但没有用,因此出现了问题。
Saichovsky

1
@Saichovsky-我检查了它在jq 1.4、1.5和1.6中是否可用。如果您使用的是jq 1.3,则必须编写.["id address"],就像通常情况下一样。
高峰

45

遇到了非常优雅的解决方案

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将对象列表中的每个对象转换为键/值对,因此我们可以使用update运算符访问.key.value分别.value使用该字段更新(覆盖)每个KV项.ip|=


该解决方案是确切的答案。选定的解决方案具有一些有用的附加功能,但不够精确或精致。您可能需要添加简要说明和完整命令。
Mike D

高超!很多次我使用“ to_entries []”只是因为我不知道这一点。
龙岗坊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.