我从curl
获得了一个非常大的JSON流(几GB)并尝试使用jq
处理它。
我要用jq
解析的相关输出打包在表示结果结构的文档中:
{
"results":[
{
"columns": ["n"],
// get this
"data": [
{"row": [{"key1": "row1", "key2": "row1"}], "meta": [{"key": "value"}]},
{"row": [{"key1": "row2", "key2": "row2"}], "meta": [{"key": "value"}]}
// ... millions of rows
]
}
],
"errors": []
}
我想用row
提取jq
数据。这很简单:
curl XYZ | jq -r -c '.results[0].data[0].row[]'
结果:
{"key1": "row1", "key2": "row1"}
{"key1": "row2", "key2": "row2"}
但是,这总是等到curl
完成。
我使用了--stream
选项来处理这个问题。我尝试了以下命令,但也等待从curl
返回完整对象:
curl XYZ | jq -n --stream 'fromstream(1|truncate_stream(inputs)) | .[].data[].row[]'
有没有办法'跳转'到data
字段并逐个解析row
而无需等待结束标记?
答案 0 :(得分:4)
(1)您将使用的香草过滤器如下:
jq -r -c '.results[0].data[].row'
(2)这里使用流解析器的一种方法是使用它来处理.results[0].data
的输出,但这两个步骤的组合可能比vanilla方法慢。
(3)要生成所需的输出,您可以运行:
jq -nc --stream '
fromstream(inputs
| select( [.[0][0,2,4]] == ["results", "data", "row"])
| del(.[0][0:5]) )'
(4)或者,您可能希望尝试以下方面:
jq -nc --stream 'inputs
| select(length==2)
| select( [.[0][0,2,4]] == ["results", "data", "row"])
| [ .[0][6], .[1]] '
对于说明性输入,上次调用的输出将为:
["key1","row1"]
["key2","row1"]
["key1","row2"]
["key2","row2"]
答案 1 :(得分:2)
获得:
{"key1": "row1", "key2": "row1"}
{"key1": "row2", "key2": "row2"}
自:
{
"results":[
{
"columns": ["n"],
"data": [
{"row": [{"key1": "row1", "key2": "row1"}], "meta": [{"key": "value"}]},
{"row": [{"key1": "row2", "key2": "row2"}], "meta": [{"key": "value"}]}
]
}
],
"errors": []
}
执行以下操作,相当于jq -c '.results[].data[].row[]'
,但使用的是:
jq -cn --stream 'fromstream(1|truncate_stream(inputs | select(.[0][0] == "results" and .[0][2] == "data" and .[0][4] == "row") | del(.[0][0:5])))'
这是做什么的:
--stream
).results[].data[].row[]
(使用select(.[0][0] == "results" and .[0][2] == "data" and .[0][4] == "row"
)"results",0,"data",0,"row"
(del(.[0][0:5])
)fromstream(1|truncate_stream(…))
模式将生成的jq流重新转换为预期的JSON
例如:
echo '{"results":[{"columns":["n"],"data":[{"row":[{"key1":"row1","key2":"row1"}],"meta":[{"key":"value"}]},{"row":[{"key1":"row2","key2":"row2"}],"meta":[{"key":"value"}]}]}],"errors":[]}' | jq -cn --stream 'fromstream(1|truncate_stream(inputs | select(.[0][0] == "results" and .[0][2] == "data" and .[0][4] == "row") | del(.[0][0:5])))'
产生所需的输出。