0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

jq 1.7の新機能ーelseなしのif

Last updated at Posted at 2024-06-29

JSON処理のコマンドラインツールであるjqが1.7にアップデートして、もうそろそろ1年です(2023年9月リリース)。1.6からの改定や新機能も定着してきたと思います。

全容はGithub上のリリースノートを見ていただくとして、今日は誰しも1度はつまずいたことのあるelse必須のifです。

これまでは

jqifは変わっていて、条件に合致しない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」の精神的には歓迎すべきでしょう。

参考

表紙 表紙

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?