JSON から必要なものを取り出すときに使う jq コマンド。使い方をすぐ忘れてしまって毎回 jq Manual を見ているので、よく使うフィルタをメモしておきます。jq のバージョンは 1.6。随時更新。
目次
- サンプルの JSON 準備
- JSON をフォーマット
- 配列の中身をすべて取り出す
- 特定の配列の要素を取り出す
- キーを指定して値を取り出す
- 複数の値を取り出す
- ダブルクォーテーションを消す
- CSV 形式で出力する
- TSV 形式で出力する
- 絞り込み検索をする
- and/or 検索
- 正規表現で検索
- 文字列の結合
- null 入力
- 集計
- 日付のフォーマット変更とタイムゾーン変更
サンプルの 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"
TSV 形式で出力する
結果をパイプでつなぎ @tsv
とすることで、TSV 形式で出力することができます。
echo $JSON | jq -r '.[] | [.Address, .ID] | @tsv'
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] | @tsv'
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] | @tsv'
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] | @tsv'
192.168.0.1 1
192.168.0.2 2
正規表現で検索
select()
の中で test()
を使うと正規表現で検索ができます。
echo $JSON | jq -r '.[] | select(.Name | test("^b")) | [.Address, .ID, .Name] | @tsv'
192.168.0.2 2 bar
192.168.0.3 3 buz
文字列の結合
文字型に +
を利用することで文字列の結合ができます。出力を加工したいときなどに使います。
echo $JSON | jq -r '.[] | [.Address + "/32", .ID] | @tsv'
192.168.0.1/32 1
192.168.0.2/32 2
192.168.0.3/32 3
null 入力
jq は通常、json データを読み込んで使いますが、-n (--null-input)
オプションで読み込むデータが無くても動かすことができます。jq の機能をサッと試したいときに使えるテクニックです。
jq -n 'now|localtime|todate'
"2022-01-09T23:40:34Z"
集計
max, min, sum, count など集計について別の記事にまとめました。
-
jqコマンドで集計 group by, max, sum, count
jq コマンドで集計(最大、合計、数、平均、並び替え)をする方法を紹介します。jq のバージョンは 1.6。 以前書いた ...
続きを見る
日付のフォーマット変更とタイムゾーン変更
日付のフォーマット変更とタイムゾーン変更について別の記事にまとめました
-
jqコマンドで日付のフォーマット変更とタイムゾーン変更
jq コマンドで日付を扱うときに、出力する日付のフォーマットを変更したり、タイムゾーンを UTC から JST に変更す ...
続きを見る