シェルスクリプトとの組合わせでjq
を書く機会があり、助かったのでメモ。
jq
とはお馴染みのJSONオペレータであり、JSONを入力して色々な操作ができる。シェルスクリプトから使うと便利だ。
そんな中、jq
とシェルスクリプトとでは「要素が無い」をどう表現するかでインピーダンスミスマッチが存在する。
jq
は素直にnull
と出力する:
% echo '{"foo": 123}' | jq -r '.bar' null
もしくは、-e
オプションを使うことでexit codeを1にすることもできる:
% echo '{"foo": 123}' | jq -re '.bar' null % echo $? 1
一方、bash等のシェルは空文字列の場合は要素が無いとみなして特殊な処理を行えるようになっていることが多い:
% unset $FOO % FOO=${FOO:-bar} # 空の場合barになる % echo $FOO bar
シェルスクリプト的な世界観では、nullと比較するよりも、文字列が空かどうかで判定することのほうが多い:
# こっちよりも・・・ if [[ "$FOO" == "null" ]]; then ... fi # こっちのがよくある if [[ -z "$FOO" ]];then ... fi
一般に、その言語でよくある書き方があるならばそちらに合わせたほうが可読性は上がる。したがって、jq
で要素を見付けられなかった場合は空文字列を返してくれると嬉しい。今回の自分のユースケースでは、exit codeを使う方式はちょっと収まりが悪かった。
調べてみると、jqのIssueで同じような事を言っている人がいた:
jqにはempty
という特殊なトークンがあるようで、以下の通りに書くと要素が無いときは空文字列を返してくれる:
% echo '{"foo": 123}' | jq -r ".bar // empty" %
ちなみに、デフォルト値が欲しいだけの場合はempty
の代わりに直接文字列を指定すればよい:
% echo '{"foo": 123}' | jq -r '.bar // "default"' default %
jqは賢いなぁ