条件式と比較
==, !=
式'a == b'は、aとbを評価した結果が等しい場合(つまり、等価なJSON値を表す場合)に'true'を生成し、それ以外の場合に'false'を生成します。特に、文字列が数値と等しいとみなされることはありません。JSONオブジェクトの等価性を調べるとき、キーの順序は関係ありません。JavaScriptを使っていた方は、jqの == が、JavaScriptの「厳密等価」演算子 === と同様であることに注意してください。
!=は「等しくない」を意味し、'a != b'は'a == b'と逆の値を返します。
実行例 1
コマンド
jq '. == false'入力
null出力 1
false実行例 2
コマンド
jq '. == {"b": {"d": (4 + 1e-20), "c": 3}, "a":1}'入力
{"a":1, "b": {"c": 3, "d": 4}}出力 1
true実行例 3
コマンド
jq '.[] == 1'入力
[1, 1.0, "1", "banana"]出力 1
true出力 2
true出力 3
false出力 4
falseif-then-else-end
if A then B else C end が B と同じ動作をするのは、A がfalseでもnullでもない値を生成する場合です。それ以外の場合は C と同じ動作をします。
if A then B end は、if A then B else . end と同じです。つまり、else 分岐は省略可能で、省略した場合は . と同じです。これは、elif で最後の else 分岐を省略した場合にも当てはまります。
falseかnullかを調べるという「真とみなすかどうか」の基準は、JavaScriptやPythonより単純です。ただし、求める条件を、より明示的に指定しなければならない場合があります。たとえば、if .name then A else B end では文字列が空かどうかは調べられません。代わりに、if .name == "" then A else B end のような式が必要です。
条件 A が複数の結果を生成する場合、B はfalseでもnullでもない各結果に対して1回ずつ評価され、C はfalseまたはnullの各結果に対して1回ずつ評価されます。
ifにさらに条件を追加するには、elif A then B 構文を使います。
実行例 1
コマンド
jq 'if . == 0 then
"zero"
elif . == 1 then
"one"
else
"many"
end'入力
2出力 1
"many">, >=, <=, <
比較演算子 >、>=、<=、< は、それぞれ、左の引数が右の引数より大きいか、以上か、以下か、より小さいかを返します。
順序は、前述の sort で説明した順序と同じです。
実行例 1
コマンド
jq '. < 5'入力
2出力 1
trueand, or, not
jqは、通常の真偽値演算子 and、or、not に対応しています。真とみなす基準はif式と同じです。false と null は「偽の値」とみなされ、それ以外はすべて「真の値」です。
これらの演算子のオペランドが複数の結果を生成する場合、演算子自体も各入力に対して結果を生成します。
実際には、not は演算子ではなく組込み関数です。そのため、専用の構文ではなく、値をパイプで渡すフィルターとして呼び出します。たとえば、.foo and .bar |
not のように使います。
この3つは、true と false の値だけを生成します。そのため、純粋な真偽値演算に使うもので、Perl/Python/Rubyでよく使われる"value_that_may_be_null or default"という書き方には使えません。このような「or」を使い、条件を評価する代わりに2つの値から選びたい場合は、後述の // 演算子を参照してください。
実行例 1
コマンド
jq '42 and "a string"'入力
null出力 1
true実行例 2
コマンド
jq '(true, false) or false'入力
null出力 1
true出力 2
false実行例 3
コマンド
jq '(true, true) and (true, false)'入力
null出力 1
true出力 2
false出力 3
true出力 4
false実行例 4
コマンド
jq '[true, false | not]'入力
null出力 1
[false, true]代替演算子://
演算子 // は、左辺の値のうち、false でも null でもないものをすべて生成します。左辺が false または null 以外の値を1つも生成しない場合、// は右辺の値をすべて生成します。
a // b という形式のフィルターは、a の結果のうち、false でも null でもないものをすべて生成します。a が結果を1つも生成しない場合、または false か null 以外の結果を生成しない場合、a
// b は b の結果を生成します。
これは既定値を与える際に便利です。.foo // 1 が 1 に評価されるのは、入力に .foo 要素がない場合です。これは、Pythonで or が使われることがある方法と似ています(jqの or 演算子は、厳密な真偽値演算専用です)。
注意:some_generator // defaults_here は、some_generator | . // defaults_here と同じではありません。後者は左辺の、false でない値、null でない値のすべてに対して既定値を生成しますが、前者はそうではありません。優先順位の規則が分かりにくくする場合があります。たとえば、false, 1 // 2 で // の左辺となるのは 1 であって、false, 1 ではありません。false, 1 // 2 は、false,
(1 // 2) と同じように解析されます。(false, null, 1) | . // 42 で // の左辺となるのは . で、常に1つの値だけを生成します。一方、(false, null, 1) // 42 の左辺は3つの値のジェネレーターです。false と null 以外の値を生成するため、既定値 42 は生成されません。
実行例 1
コマンド
jq 'empty // 42'入力
null出力 1
42実行例 2
コマンド
jq '.foo // 42'入力
{"foo": 19}出力 1
19実行例 3
コマンド
jq '.foo // 42'入力
{}出力 1
42実行例 4
コマンド
jq '(false, null, 1) // 42'入力
null出力 1
1実行例 5
コマンド
jq '(false, null, 1) | . // 42'入力
null出力 1
42出力 2
42出力 3
1try-catch
エラーは、try EXP catch EXP を使って捕捉できます。最初の式を実行し、失敗した場合は、エラーメッセージを入力として2番目の式を実行します。ハンドラーが何かを出力した場合、それは、試した式の出力であるかのように出力されます。
try EXP という形式は、例外ハンドラーとして empty を使います。
実行例 1
コマンド
jq 'try .a catch ". is not an object"'入力
true出力 1
". is not an object"実行例 2
コマンド
jq '[.[]|try .a]'入力
[{}, true, {"a":1}]出力 1
[null, 1]実行例 3
コマンド
jq 'try error("some exception") catch .'入力
true出力 1
"some exception"制御構造から抜け出す
try/catchの便利な用途の1つは、reduce、foreach、while などの制御構造から抜け出すことです。
例:
# Repeat an expression until it raises "break" as an
# error, then stop repeating without re-raising the error.
# But if the error caught is not "break" then re-raise it.
try repeat(exp) catch if .=="break" then empty else error
jqには、「抜け出す」または「戻る」先として使う、名前付きの字句的なラベルの構文があります。
label $out | ... break $out ...
式 break $label_name は、最も近い左側の label $label_name が empty を生成したかのように、プログラムを動作させます。
break と対応する label の関係は字句的なものです。ラベルがbreakから「見える」位置にある必要があります。
たとえば、reduce から抜け出すには、次のようにします。
label $out | reduce .[] as $item (null; if .==false then break $out else ... end)
次のjqプログラムは、構文エラーを生成します。
break $out
ラベル $out が見える位置にないためです。
エラー抑制/オプショナル演算子:?
演算子 ? を EXP? として使う書き方は、try EXP の省略形です。
実行例 1
コマンド
jq '[.[] | .a?]'入力
[{}, true, {"a":1}]出力 1
[null, 1]実行例 2
コマンド
jq '[.[] | tonumber?]'入力
["1", "invalid", "3", 4]出力 1
[1, 3, 4]訳注
訳注:原文の注意書きには、パイプを使った形がfalseでもnullでもない値に既定値を生成するという一文がありますが、同じ原文の説明と例では、falseまたはnullに対して既定値を生成し、それ以外の値はそのまま出力しています。保持した例では、(false, null, 1) // 42の出力は1だけで、(false, null, 1) | . // 42の出力は42、42、1です。原文の一文は無言で書き換えず、例との食い違いをここで区別しています。