我正在使用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对?
答案 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")))