jq map_values在非常大的文件上

时间:2019-05-03 15:58:53

标签: json select jq keyvaluepair

我正在使用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的快速查询,并且还可以为我提供key:value对?

3 个答案:

答案 0 :(得分:1)

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

test/1

(使用keys_unsorted[] as $k | select(.[$k] | test("another")) | [$k, .[$k]] 会不必要地效率低下,除非您完全了解其复杂性,否则使用map_values可能不是一个好主意。)

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

contains

非常大的文件

对于太大而无法正常读入jq的文件,您可以使用jq的流解析器,即使用. as $in | reduce keys_unsorted[] as $k ({}; if ($in[$k] | test("another")) then .[$k] = $in[$k] else . end) 命令行选项。不幸的是,这说起来容易做起来难,但是一个简单的方法就是使用--stream,例如在jq --stream filter on multiple values of same key

答案 1 :(得分:0)

让我为您提供一个替代解决方案-一种用于JSON的步行路径Unix工具: jtc 。在jtc中,您将查询“编码”到步行路径本身,因此查询看起来像:

bash $ jtc -w'<\banother\b>R:' -l largefile.json
"prop2": "another large string"
"prop3": "yet another large string"
bash $ 

,其中<...>R中的值实际上是一个RE模式(即示例中的\banother\b)。而且,如果您希望将结果的步行条目包装到JSON数组中,请使用-j选项

披露:我是jtc工具的创建者

答案 2 :(得分:-1)

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

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