给定一个巨大的(15GB(深度嵌套(12+对象层(JSON文件,我如何找到所有值为string
的名为id
的键的路径?
一个大规模简化的示例文件:
{
"a": [
{
"id": 3,
"foo": "red"
}
],
"b": [
{
"id": "7",
"bar": "orange",
"baz": {
"id": 13
},
"bax": {
"id": "12"
}
}
]
}
正在寻找一个不那么丑陋的解决方案,在这个解决方案中,我不会耗尽RAM,并且不得不在最后踢到grep(叹气(。(我没能想出如何将to_entries
链接到其中。如果这是我应该尝试做的事情的话。(
丑陋的解决方案1:
$ cat huge.json | jq 'path(..|select(type=="string")) | join(".")' | grep -E '.id"$'
"b.0.id"
"b.0.bax.id"
丑陋的解决方案2:
$ cat huge.json | jq --stream -c | grep -E '"id"],"'
[["b",0,"id"],"7"]
[["b",0,"bax","id"],"12"]
应该这样做。
jq --stream 'select(.[0][-1] == "id" and (.[1] | strings)) | .[0]' file
顺便说一下,你的第一个丑陋的解决方案可以简化为:
jq 'path(.. .id? | strings)' file
在开始使用第二个解决方案时对输入进行流式处理,但添加了一些过滤。您不想将全部内容读入内存。而且。。。UUOC。
$ jq --stream '
select(.[0][-1] == "id" and (.[1]|type) == "string")[0]
| join(".")
' huge.json
感谢oguz和Jeff!美丽的它运行6.5分钟(在我的旧笔记本电脑上(,从不使用超过21MB的RAM,并且能满足我的需求<3
$ jq --stream -c 'select(.[0][-1] == "id" and (.[1]|type) == "string")' huge.json