JSON の操作なら jq コマンドで十分なのですが、シェルの中で JSON をいい感じに扱いたい時ってありますよね。
配列の中から特定のキーの値を抜き出す。
そんなイメージの処理を書きたい時です。
「いやいや、それでも jq コマンドで一発でしょ」
って感じになると思いますが、その過程で別のキーの値も参照したいとか、結局は行単位で自由に操作したいケースってあると思うのですよね。
今回は、シェルの中で JSON の配列の 1 行 1 行を抜き出す処理を紹介します。
jqコマンドで特定のキーの値を抜き出す
純粋に特定のキーの値を抜き出してくるだけなら、確かに jq コマンドで事足ります。
値のダブルクォーテーションも除去するならこんな感じですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [rira.json] { "name": "リラックマ", "color": "brown" } { "name": "コリラックマ", "color": "white" } { "name": "キイロイトリ", "color": "yellow" } |
1 2 3 4 5 | $ cat rira.json | jq -r .[].name リラックマ コリラックマ キイロイトリ |
シェルでループする
上記では「name」だけ取得しましたが、シェルでループさせれば「color」を使うこともできます。
JSON のキー項目が増えれば増えるほど 1 行ずつ処理した方が楽です。
jq コマンドでも強引にできそうな部分はありますが。
例えばこれだと、う~ん微妙・・・。
1 2 3 4 5 6 7 8 | $ cat rira.json | jq -r '.[].name,.[].color' リラックマ コリラックマ キイロイトリ brown white yellow |
これだと name と color が順番に出力されるようになったので、もう少し応用すれば利用価値がありそうでしょうか。
1 2 3 4 5 6 7 8 | $ cat rira.json | jq -r '.[] | .name,.color' リラックマ brown コリラックマ white キイロイトリ yellow |
っと、jq でも頑張ればなんとかできそうですが、シェルでループさせた方が楽なのは間違いありません。
シェルに置き換えて、1 行ずつ取り出してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/sh JSON=`cat rira.json` JSON_LEN=`echo ${JSON} | jq length` for i in `seq 0 $((${JSON_LEN} - 1))`; do row=`echo ${JSON} | jq .[${i}]` echo ${row} name=`echo ${row} | jq -r .name` color=`echo ${row} | jq -r .color` echo "name: ${name}, color: ${color}" done |
実行してみるとこんな感じの結果になります。
{ “name”: “リラックマ”, “color”: “brown” }
name: リラックマ, color: brown
{ “name”: “コリラックマ”, “color”: “white” }
name: コリラックマ, color: white
{ “name”: “キイロイトリ”, “color”: “yellow” }
name: キイロイトリ, color: yellow
まとめ
シェルスクリプトで、JSON ファイルを読み込んで中身を出力してみました。
jq コマンドを応用すれば、もっと多くの JSON 操作ができますが、純粋にシェルで活用した方が便利な場合も多いです。
ワンライナーでカッコよく書ければベターですが、複数行でも簡潔にわかりやすい方がベストです。
Github Actions でワークフローを定義する際に、シェルを使う機会も増えてくるので、TIPS 的なネタは溜めておきたいですね。
って、CI でそんな複雑なことしたくないのが本音ですが・・・。