JSON処理のコマンドラインツールであるjqが1.7にアップデートして、もうそろそろ1年です(2023年9月リリース)。1.6からの改定や新機能も定着してきたと思います。
全容はGithub上のリリースノートを見ていただくとして、今日は誰しも1度はつまずいたことのあるelse必須のifです。
これまでは
jqのifは変わっていて、条件に合致しないelse時の処理も必ず記述しなければなりませんでした。elseブロックでなにもしたくないときは、明示的にemptyと書きます。
入力が[1, 2, 3, 4]で、要素が偶数のときは「2 even」のように出力するが、奇数のときはなにもしないのなら、次のように書きます。
$ jq-1.6 --version # バージョンを確認
jq-1.6
$ echo '[1, 2, 3, 4]' | jq-1.6 '.[] | if . % 2 == 0 then tostring + " even" else empty end'
"2 even"
"4 even"
else emptyを除くとエラーが発生します。
$ echo '[1, 2, 3, 4]' | jq-1.6 '.[] | if . % 2 == 0 then tostring + " even" end'
jq: error: syntax error, unexpected end (Unix shell quoting issues?) at <top-level>, line 1:
.[] | if . % 2 == 0 then tostring + " even" end
jq: error: Possibly unterminated 'if' statement at <top-level>, line 1:
.[] | if . % 2 == 0 then tostring + " even" end
jq: 2 compile errors
これからは
条件が合致しないときのelse emptyは省くことができます。
ただし、省かれたときは.が実行されます。つまり、else .と解釈されるので、上記をそのまま実行すると、思ったのと違う結果になります。
$ jq --version
jq-1.7.1 # 1.7です
$ echo '[1, 2, 3, 4]' | jq '.[] | if . % 2 == 0 then tostring + " even" end'
1 # デフォルトで else 時には .
"2 even"
3 # ここもそう
"4 even"
なので、省略したいのなら、else時にしたいことを実行するようにロジックを反転しなければなりません。
$ echo '[1, 2, 3, 4]' | jq '.[] | if . % 2 != 0 then empty end'
2
4
これだと「2 even」にはならないので、パイプ経由で.の処理を加えます。
$ echo '[1, 2, 3, 4]' | jq '.[] | if . % 2 != 0 then empty end | tostring + " even"'
"2 even"
"4 even"
おわりに
$ echo '[1, 2, 3, 4]' | jq '.[] | if . % 2 == 0 then tostring + " even" else empty end'
$ echo '[1, 2, 3, 4]' | jq '.[] | if . % 2 != 0 then empty end | tostring + " even"'
どちらが見やすいかと言われるとどちらも微妙です。用例がよくなく、この新機能の真価がわかりにくいだけかもしれません。
同じことをするのなら、条件式が満たされるときのみ.を出力をするselectのほうがわかりがよいでしょう。これなら、v1.6でも動作します。
$ echo '[1, 2, 3, 4]' | jq '.[] | select(. % 2 == 0) | tostring + " even"'
"2 even"
"4 even"
あるいはこう。
$ echo '[1, 2, 3, 4]' | jq 'map(select(. % 2 == 0) | tostring + " even")[]'
"2 even"
"4 even"
いずれにせよ、さらに多様な書き方ができるようになったので、「There's more than one way to do it」の精神的には歓迎すべきでしょう。
参考
-
./jq ...
jqのオフィシャルサイトです(英文)。 -
Github jqland/jq Releases ...
jqのリリースノートです(英文)。 - 『jqハンドブック』(2021)...
if、select、代替演算子の//、try-catchなど制御文関係はこの本の第10章で紹介しています。ご購入はこちらから【 出版社 | honto | amazon.co.jp | ヨドバシカメラ 】。 - 「jqのむだづかい」 ...
jqではまずやろうとは思わない処理の探求記録です。完成版は他の(通常機能な)レシピとともに『jqクックブック』(2023)に掲載しました。ご購入はこちらから【 出版社 | honto | amazon.co.jp | ヨドバシカメラ 】。

