notebook

都内でWEB系エンジニアやってます。

jqで複数ハッシュのmergeをする

RubyでいうHash.merge的な処理をjqでもやりたいとき

集計結果をいくつかのファイルに出力しておき最後にサマリーとしてJSONにまとめたいときなどに使う

書いていて感じたけどあまりこういう機会はないかもしれない…

  • 01.json
{
  "hoge": 1,
  "fuga": 2
}
  • 02.json
{
  "fuga": 3,
  "piyo": 4 
}

結論

$ cat 01.json 02.json | jq -s 'reduce .[] as $n ({}; . * $n)'
{
  "hoge": 1,
  "fuga": 3,
  "piyo": 4
}

キーの値は後に来たものが優先される

$ cat 02.json 01.json | jq -s 'reduce .[] as $n ({}; . * $n)'
{
  "fuga": 2,
  "piyo": 4,
  "hoge": 1
}

流れを追う

-sで複数ファイルの出力結果を配列にする

  • --slurp
$ cat 01.json 02.json | jq -s
[
  {
    "hoge": 1,
    "fuga": 2
  },
  {
    "fuga": 3,
    "piyo": 4
  }
]

ハッシュどうしのマージには*演算子で行う

$ cat 01.json 02.json | jq -s '.[0] * .[1]'
{
  "hoge": 1,
  "fuga": 3,
  "piyo": 4
}

reduceで各ファイルの結果を順々にマージして最終的に1つのハッシュにする

例では2つのファイルで決め打ちだが、ファイルやハッシュがもっとたくさんある場合などは配列の中身すべてに対して処理してあげる必要がある

ということでreduceを使う

初期値は空のハッシュ

$ cat 01.json 02.json | jq -s 'reduce .[] as $n ({}; . * $n)'
{
  "hoge": 1,
  "fuga": 3,
  "piyo": 4
}

また1つjqレベルが上がりました