使用jq提取多JSON对象:内存占用与单次提取多结果问询
关于jq处理大JSON文件的两个问题
背景
我目前用jq从较大的JSON文件中每次提取一个JSON块,写入每行一个JSON对象的文件用于后续处理。示例JSON格式如下:
{ "date": "2023-07-30", "results1":[ { "data": [ {"row": [{"key1": "row1", "key2": "row1"}]}, {"row": [{"key1": "row2", "key2": "row2"}]} ] }, { "data": [ {"row": [{"key1": "row3", "key2": "row3"}]}, {"row": [{"key1": "row4", "key2": "row4"}]} ] } ], "results2":[ { "data": [ {"row": [{"key3": "row1", "key4": "row1"}]}, {"row": [{"key3": "row2", "key4": "row2"}]} ] }, { "data": [ {"row": [{"key3": "row3", "key4": "row3"}]}, {"row": [{"key3": "row4", "key4": "row4"}]} ] } ] }
当前执行的命令为:
jq -rc ".results1[]" my_json.json
该命令可正常运行,但看起来jq会把整个文件读入内存来提取目标内容。现提出两个问题:
问题1:执行上述命令时,jq是否会将整个文件读入内存?
是的。默认情况下,jq的工作机制是先将整个JSON文件加载到内存中,完整解析为内部数据结构后,再执行指定的查询操作。哪怕只需要提取文件中的一小部分数据,它也会先完成全文件的读取与解析,这是jq常规模式的特性。
如果处理超大型JSON文件,这种模式可能占用较多内存,但你提到当前内存不是问题,无需切换到--stream模式——该模式无需加载全文件,但解析逻辑更复杂,速度也会更慢。
问题2:能否通过单次调用jq同时提取results1[]和results2[],避免两次读取文件?
可以。利用jq的outputs()函数(需jq 1.6及以上版本支持),就能在一次读取源文件的情况下,将两个数组的内容分别写入不同的输出文件,生成符合JSON Lines格式的结果。
具体命令如下:
jq -rc ' .results1[] | outputs("results1_output.json"), .results2[] | outputs("results2_output.json") ' my_json.json
输出结果
results1_output.json内容:
{"data":[{"row":[{"key1":"row1","key2":"row1"}]},{"row":[{"key1":"row2","key2":"row2"}]}]} {"data":[{"row":[{"key1":"row3","key2":"row3"}]},{"row":[{"key1":"row4","key2":"row4"}]}]}
results2_output.json内容:
{"data":[{"row":[{"key3":"row1","key4":"row1"}]},{"row":[{"key3":"row2","key4":"row2"}]}]} {"data":[{"row":[{"key3":"row3","key4":"row3"}]},{"row":[{"key3":"row4","key4":"row4"}]}]}
这个命令会一次性将整个JSON文件读入内存,分别遍历results1和results2数组,把每个数组元素直接写入对应的输出文件,全程只读取一次源文件,完全匹配需求。
内容的提问来源于stack exchange,提问作者fsumathguy
相关产品推荐
相关产品推荐

