jq map_values 在非常大的文件上

Posted

技术标签:

【中文标题】jq map_values 在非常大的文件上【英文标题】:jq map_values on very large file 【发布时间】:2019-05-03 15:58:52 【问题描述】:

我正在使用 jq 在一个非常大的 JSON 文件 (500MB+) 中查找模式,该文件具有以下平面对象结构:


   "prop1": "large string",
   "prop2": "another large string",
   "prop3": "yet another large string",
   ...

以下查询运行良好,返回结果不到 15 秒:

jq 'map(select(contains("PATTERN")==true))' largefile.json > res.json

但这会返回一个包含模式的字符串数组,所以我丢失了属性名称。 当我尝试使用 map_values 时,我也可以获取属性名称,如:

jq 'map_values(select(contains("PATTERN")==true))' largefile.json > res.json

查询需要很长时间。

是否有类似 map 的等价查询,它还可以为我提供键:值对?

【问题讨论】:

你能和pastebin分享那个json的一部分(如果不是私有的话)吗? 对不起,文件是私有的,但是,是的,非常容易重新创建,只需将随机字符串值按顺序添加到道具中。 顺便说一下,map_values(select(...)) 的行为因 jq 的一个版本而异。 【参考方案1】:

由于您的 JSON 文件对于 jq 读取来说不是太大,因此一个简单有效的解决方案(以使用 jq 将文件读入内存为模)是使用 keys_unsorted/0test/1

keys_unsorted[] as $k
| select(.[$k] | test("another"))
| [$k, .[$k]]

(使用map_values 会不必要地低效,除非您完全了解其复杂性,否则使用contains 可能不是一个好主意。)

如果您要求输出是单个对象,您可以调整上述内容,或者(以输出对象所需的内存为代价):

. as $in
| reduce keys_unsorted[] as $k (;
    if ($in[$k] | test("another"))
    then  .[$k] = $in[$k]
    else . end)

非常大的文件

对于太大而无法正常读入 jq 的文件,您可以使用 jq 的流式解析器,即使用 --stream 命令行选项。不幸的是,这说起来容易做起来难,但一个简单的方法是使用 atomize 定义例如在jq --stream filter on multiple values of same key

【讨论】:

您在此处提供的 keys_unsorted 示例因此不会产生正确的 JSON 对象。文件的顶部和底部缺少大括号。 您的问题要求key:value 对。也许你应该澄清你的要求,例如按照minimal reproducible example。同时,也许您可​​以弄清楚如何调整 jq 程序以实现您想要的,例如从($k): .[$k]开始【参考方案2】:

只需使用with_entries/1,它就可以根据键和/或值有效地过滤掉对象的属性。

with_entries(select(.value | contains("PATTERN")))

【讨论】:

这绝对可以按我的意愿工作,快速并将对象键留在我想要的位置。谢谢你,@杰夫

以上是关于jq map_values 在非常大的文件上的主要内容,如果未能解决你的问题,请参考以下文章

在非常大的文件C#的所有行上循环[重复]

有没有办法在 nginx 上使用 django 上传一个非常大的文件?

优雅的查看json文件

如何使用 jq 流过滤 JSON [重复]

FFprobe 在非常大的 .mov 文件上报告 Invalid sample_count

gcc需要很多内存来编译堆栈上具有非常大的对象的c ++文件