[英]Parsing JSON record-per-line with jq?
我有一個工具在每一行輸出JSON記錄,我想用jq
處理它。
輸出看起來像這樣:
{"ts":"2017-08-15T21:20:47.029Z","id":"123","elapsed_ms":10}
{"ts":"2017-08-15T21:20:47.044Z","id":"456","elapsed_ms":13}
當我將此傳遞給jq
如下:
./tool | jq 'group_by(.id)'
...它輸出一個錯誤:
jq: error (at <stdin>:1): Cannot index string with string "id"
如何讓jq
處理每行JSON記錄數據?
使用--slurp
(或-s
)開關:
./tool | jq --slurp 'group_by(.id)'
它輸出以下內容:
[
[
{
"ts": "2017-08-15T21:20:47.029Z",
"id": "123",
"elapsed_ms": 10
}
],
[
{
"ts": "2017-08-15T21:20:47.044Z",
"id": "456",
"elapsed_ms": 13
}
]
]
...然后你可以進一步處理。 例如:
./tool | jq -s 'group_by(.id) | map({id: .[0].id, count: length})'
正如@JeffMercado指出的那樣,jq處理JSON流很好,但是如果你使用group_by
,那么你必須確保它的輸入是一個數組。 在這種情況下,可以使用-s
命令行選項來完成; 如果你的jq有inputs
過濾器,那么它也可以使用該過濾器和-n
選項一起完成。
但是,如果你有一個帶inputs
的jq版本(在jq 1.5中可用),那么更好的方法是使用group_by
的以下流式變體:
# sort-free stream-oriented variant of group_by/1
# f should always evaluate to a string.
# Output: a stream of arrays, one array per group
def GROUPS_BY(stream; f): reduce stream as $x ({}; .[$x|f] += [$x] ) | .[] ;
用法示例: GROUPS_BY(inputs; .id)
請注意,您將要使用-n
命令行選項。
這種流式變體有兩個主要優點:
group_by/1
不同。 請注意,上面定義的GROUPS_BY/2
遵循此類流式過濾器的慣例,因為它產生一個流。 其他變體當然是可能的。
以下說明如何節省內存。 假設任務是產生.id值的頻率計數。 單調的解決方案是:
GROUPS_BY(inputs; .id) | [(.[0]|.id), length]
更經濟,更好的解決方案是:
GROUPS_BY(inputs|.id; .) | [.[0], length]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.