jq 便利ですよね。
jq 使ってます。みんなあれ整形程度にしか使ってなかったり、絞込にしか使ってない気と思うんですよね
jq である条件を満たすオブジェクトを取り出したい
SQLのselect where みたいに select {} where [].name = 'takuya' みたいな jq がかけたら最高なんですよ。
条件マッチしたノードを取り出す例
$ echo '[ { "a":1 }, { "x": 1 } ]' | jq ' .[] | select(.x) '
{
"x": 1
}
出来るんです。マニュアルに有りました。ああ。これは最高だ。
単純なところから、見ていく
いきなり select 見ても何のことかわからないので、単純なところから見ていくことにする。
単純な整形
jq を使って整形をするよくある例です。これは jq . と書いてます。つまりカレントノードを出力しろって意味です。
単純な整形の例
$ echo '[{},{}]' | jq .
[
{},
{}
]
配列の中身を出す
配列の中を自動で走査して中身を取り出してくれるのが、こちらにになります。 jq .[] は jq の最上位のノードのひとつ下の配列をIterationして中身をくれって事になります。
配列の中身を出力取り出す例
$ echo '[1,2,3]' | jq '.[]' 1 2 3
配列の指定したINDEXを取り出す。
配列のなかに、インデックスを指定すると、指定した番号のものが取り出せる。
配列の指定したINDEXを取り出す例
$ echo '[1,2,3]' | jq '.[1]' 2
さらにこれは、一つだけじゃなくさらに突っ込んだ書き方ができる。
配列の中身の順番を複数指定してしまう例
$ echo '[1,2,3]' | jq '.[0,2,1]' # 順序も 1 3 2 $ echo '[1,2,3]' | jq '.[0,2]' # 選択も 1 3
要素がオブジェクトで ハッシュキーから取り出す
選択対象となる要素がハッシュ(オブジェクト)でその中をStringをキーに取り出していきたいとき。
オブジェクトの中身だけを取り出したい。
$ echo '{ "a":1 , "b":2 }' | jq '.a'
1
$ echo '{ "a":1 , "b":2 }' | jq '.b'
2
ネストしたオブジェクトでも大丈夫。
# ネスト 1段 ・ネスト2段
$ echo '{ "a": { "x": 1 }, "b":2 }' | jq '.a'
{
"x": 1
}
$ echo '{ "a": { "x": 1 }, "b":2 }' | jq '.a.x' #ネスト 2段
1
配列とオブジェクトの選択の組み合わせ。
ここまで見た配列とオブジェクトの指定をjq で行う場合を組み合わせると次のようになる。
配列とオブジェクトを同時に使う。
$ echo '[ { "a":1 }, { "x": 1 } ]' | jq '.' # まずは単純に整形
[
{
"a": 1
},
{
"x": 1
}
]
$ echo '[ { "a":1 }, { "x": 1 } ]' | jq '.[]' # 配列要素ごとにprint
{
"a": 1
}
{
"x": 1
}
$ echo '[ { "a":1 }, { "x": 1 } ]' | jq '.[].a' # 配列の要素内で検索
1
true/falseに変形(検索条件を書く
ここで、更に検索条件を足して、書き換え処理を行う。map 処理です。
配列の各要素をその値によって書き換えていきます。
jq で要素のオブジェクトを書き換え true/falseにする
$ echo '[ { "a":1 }, { "x": 1 } ]' | jq '(.[].a==1)'
true
false
最後にselect と組み合わせる。
true / false に変形することが出来たらそれをフィルタする。 map /reduce / filter の概念が理解できてればかんたんです。
$ echo '[ { "a":1 }, { "x": 1 } ]' | jq '.[] | select (.a==1)' # a == 1 のものだけ
{
"a": 1
}
$ echo '[ { "a":1 }, { "x": 1 } ]' | jq ' .[] | select(.x) ' # 'x': object が存在するものだけ
{
"x": 1
}
個人的感想
jq 便利すぎてやばい。STDIOとパイプをJSONと組み合わせたxargs にかわる新しい概念かもしれない。
参考資料
まにゅあるにあったわ。。