Lambdaカクテル

京都在住Webエンジニアの日記です

jqでキーに対応する要素がないときnullの代わりに空文字を返すにはemptyを活用すると良い

シェルスクリプトとの組合わせで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で同じような事を言っている人がいた:

github.com

jqにはemptyという特殊なトークンがあるようで、以下の通りに書くと要素が無いときは空文字列を返してくれる:

% echo '{"foo": 123}' | jq -r ".bar // empty"
%

ちなみに、デフォルト値が欲しいだけの場合はemptyの代わりに直接文字列を指定すればよい:

% echo '{"foo": 123}' | jq -r '.bar // "default"'
default
%

jqは賢いなぁ

Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?