对于如此大的文件,您可能希望在两个单独的调用中执行此操作,一个用于获取计数,另一个用于实际输出 csv。如果您想将整个文件读入内存,您可以一次性完成,但我们绝对不想这样做,我们希望尽可能将其流式传输。
在将命令的结果存储到变量时,事情变得有点难看,写入文件可能更简单。但如果我们不需要,我宁愿不使用临时文件。
REM assuming in a batch file
for /f "usebackq delims=" %%i in (`jq -n --stream "reduce (inputs | .[0][1] + 1) as $l (0; if $l > . then $l else . end)" input.json`) do set cols=%%i
jq -rn --stream --argjson cols "%cols%" "[range($cols)|\"labels\"],(fromstream(1|truncate_stream(inputs))|[.[],(range($cols-length)|null)])|@csv" input.json
> jq -n --stream "reduce (inputs | .[0][1] + 1) as $l (0; if $l > . then $l else . end)" input.json
对于获取列数的第一次调用,我们只是利用了这样一个事实,即数组值的路径可用于指示数组的长度。我们只想在所有项目中取最大值。
> jq -rn --stream --argjson cols "%cols%" ^
"[range($cols)|\"labels\"],(fromstream(1|truncate_stream(inputs))|[.[],(range($cols-length)|null)])|@csv" input.json
然后输出其余部分,我们只取labels 数组(假设它是对象上的唯一属性)并用null 填充它们直到$cols 计数。然后输出为csv。
如果标签位于与您的示例不同的深度嵌套路径中,则需要根据适当的路径进行选择。
set labelspath=foo.bar.labels
jq -rn --stream --argjson cols "%cols%" --arg labelspath "%labelspath%" ^
"($labelspath|split(\".\")|[.,length]) as [$path,$depth] | [range($cols)|\"labels\"],(fromstream($depth|truncate_stream(inputs|select(.[0][:$depth] == $path)))|[.[],(range($cols-length)|null)])|@csv" input.json