我有一个非常大的文件,其结构如下:
{
"users": { ... },
...
"stats": {
"daily": {
"k1": { ... },
"k2": { ... },
...
"kN": { ... }
},
"monthly": {
"p1": { ... },
"p2": { ... },
...
"pN": { ... }
}
}
}
stats
中只有两个键:daily
和monthly
,它们都包含大量的键值对。
我想分别对.stats.daily
和.stats.monthly
中的所有键-值对进行流处理。
我不知道如何编辑cookbook中的atomize
函数来完成我想做的事情。下面是我正在尝试但不成功的方法:
jq -nc --stream '
def atomize(s):
fromstream(foreach s as $in ( {previous:null, emit: null};
if ($in | length == 2) and ($in|.[0][0]) != .previous and .previous != null
then {emit: [[.previous]], previous: $in|.[0][0]}
else { previous: ($in|.[0][0]), emit: null}
end;
(.emit // empty), $in) ) ;
atomize(2|truncate_stream(inputs | select(.[0][0] == "daily"))
有人能解释一下它是如何工作的,以及如何针对我的用例修复它吗?谢谢
2条答案
按热度按时间pprl5pva1#
既然您已经指出要将“每日”值与“每月”值分开处理,那么让我们关注前者。
为此,让我们仅使用
fromstream
和truncate_stream
开始:输入与给出的示例类似,但经过调整,使其成为有效的JSON:
将产生:
如果你有jq 1.6,那么上面的jq过滤器可以简化为:
现在我们只需要使用
atomize
而不是fromstream
就可以得到想要的结果,例如,使用jq 1.6,我们可以看到:将产生:
调用
效率提升
假设输入中的对象没有重复的键,则上述解决方案可以被流线化,使得一旦感兴趣的键已经被处理,则不进行进一步的处理。这可以使用如下定义的
run/3
来实现。或者用jq 1.6:
run/3
vvppvyoh2#
jq流解析器(由--stream命令行选项激活)可以经济地处理非常大的JSON输入,但即使是相对简单的任务也可能使用起来相当棘手,因此命令行实用程序jm and jm.py(前者基于“JSON Machine”,后者使用流Python解析器)可能会很有用。
无论如何,下面是使用这些实用程序完成当前任务的一些非常简单的解决方案:
请注意,jm和www.example.com都jm.py是为处理非常大的JSON输入而设计的。
免责声明:jm和www.example.com脚本都是我写jm.py的,但它们只是分别 Package 了JSON机器和ijson。