簡體   English   中英

使用jq解析每行JSON記錄?

[英]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命令行選項。

這種流式變體有兩個主要優點:

  1. 它通常需要較少的內存,因為它不需要整個輸入流的副本在處理時保存在內存中;
  2. 它可能更快,因為它不需要任何排序操作,這與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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM