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 にかわる新しい概念かもしれない。
参考資料
まにゅあるにあったわ。。