
JSON から必要なものを取り出すときに使う jq コマンド。使い方をすぐ忘れてしまって毎回 jq Manual を見ているので、よく使うフィルタをメモしておきます。jq のバージョンは 1.6。随時更新。
目次
- サンプルの JSON 準備
- JSON をフォーマット
- 配列の中身をすべて取り出す
- 特定の配列の要素を取り出す
- キーを指定して値を取り出す
- 複数の値を取り出す
- ダブルクォーテーションを消す
- CSV形式で出力する
- and/or 検索
- 正規表現で検索
サンプルの JSON 準備
サンプルとして以下の JSON を使います。ターミナルで以下のコマンドを実行して $JSON
という変数に入れておきます。
JSON=$(cat << EOS
[
{
"Address": "192.168.0.1",
"ID": "1",
"Name": "foo",
"Version": "1.0.0",
"Status": "ready"
},
{
"Address": "192.168.0.2",
"ID": "2",
"Name": "bar",
"Version": "1.0.1",
"Status": "down"
},
{
"Address": "192.168.0.3",
"ID": "3",
"Name": "buz",
"Version": "2.0.0",
"Status": "ready"
}
]
EOS
)
JSON をフォーマット
一番単純なフィルタである .
を使って JSON をフォーマットできます。改行やスペースが入っていなくて JSON が見づらい場合などに使えます。
例えばサンプルの JSON のスペースと改行を取り除くとこんな感じで見づらいですが
$ echo $JSON | tr -d '\n '
[{"Address":"192.168.0.1","ID":"1","Name":"foo","Version":"1.0.0","Status":"ready"}, ...
jq
コマンドでJSON を再フォーマットするときれいな出力になります。
$ echo $JSON | tr -d '\n ' | jq '.'
[
{
"Address": "192.168.0.1",
"ID": "1",
"Name": "foo",
"Version": "1.0.0",
"Status": "ready"
},
...
配列の中身をすべて取り出す
サンプルの JSON は全体が配列で囲まれています。.[]
と指定することで配列の中のオブジェクトをすべて取り出すことができます。
$ echo $JSON | jq '.[]'
{
"Address": "192.168.0.1",
"ID": "1",
"Name": "foo",
"Version": "1.0.0",
"Status": "ready"
}
{
"Address": "192.168.0.2",
"ID": "2",
"Name": "bar",
"Version": "1.0.1",
"Status": "down"
}
...
特定の配列の要素を取り出す
.[0]
のように配列の添字(インデックス)を指定すると、指定した配列の要素を取り出すことができます。
$ echo $JSON | jq '.[0]'
{
"Address": "192.168.0.1",
"ID": "1",
"Name": "foo",
"Version": "1.0.0",
"Status": "ready"
}
キーを指定して値を取り出す
.Address
のようにオブジェクトのキーを指定すると、値を取り出すことができます。
$ echo $JSON | jq '.[].Address'
"192.168.0.1"
"192.168.0.2"
"192.168.0.3"
複数の値を取り出す
キーをカンマで区切ると、複数の値を取り出すことができます。今回の例のように配列の中に複数のオブジェクトがある場合は、フィルタで先に配列の中身を取り出しパイプで繋ぐことで、出力結果が配列の要素ごとにまとまります。foreach 文のようなイメージです。
$ echo $JSON | jq '.[] | .Address, .ID'
"192.168.0.1"
"1"
"192.168.0.2"
"2"
"192.168.0.3"
"3"
ダブルクォーテーションを消す
jq で取得した結果を他の処理にわたす際にダブルクォーテーションが邪魔になることがあります。-r(--raw-output)
オプションで消すことができます。
$ echo $JSON | jq -r '.[] | .Address, .ID'
192.168.0.1
1
192.168.0.2
2
192.168.0.3
3
CSV形式で出力する
結果をパイプでつなぎ @csv
とすることで、CSV 形式で出力することができます。@csv
に渡す値は配列にする必要があります。ダブルクォーテーションが自動で付与されるため、-r
オプションの併用をしないと結果が見づらくなります。
$ echo $JSON | jq -r '.[] | [.Address, .ID] | @csv'
"192.168.0.1","1"
"192.168.0.2","2"
"192.168.0.3","3"
絞り込み検索をする
select()
関数を使うことで値の絞り込み検索ができます。たとえば Address が 192.168.0.1 のオブジェクトだけを出力したい場合は以下のようにします。
$ echo $JSON | jq -r '.[] | select(.Address == "192.168.0.1") | [.Address, .ID] | @csv'
"192.168.0.1","1"
and/or 検索
select()
の中で and/or
のキーワードで検索条件の追加ができます。
and 検索
$ echo $JSON | jq -r '.[] | select(.Version == "2.0.0" and .Status == "ready") | [.Address, .ID, .Version, .Status] | @csv'
"192.168.0.3","3","2.0.0","ready"
or 検索
$ echo $JSON | jq -r '.[] | select(.Address == "192.168.0.1" or .Address =="192.168.0.2") | [.Address, .ID] | @csv'
"192.168.0.1","1"
"192.168.0.2","2"
正規表現で検索
select()
の中で test()
を使うと正規表現で検索ができます。
$ echo $JSON | jq -r '.[] | select(.Name | test("^b")) | [.Address, .ID, .Name] | @csv'
"192.168.0.2","2","bar"
"192.168.0.3","3","buz"