トラック
/
jq
jq
/
演習
/
ラザニア
ラザニア

ラザニア

学習演習

はじめに

変数

jqのプログラムは_式のパイプライン_であることを思い出しましょう。 変数の代入は次のルールに従います。_変数の代入_とは、次のような形をした式です。

... | expr as $varname | ...

フィルターの出力は入力と同じ

恒等式.と同じように、_変数の代入_の出力は入力と同じです。 変数の値を設定することは副作用です。

次の例は、代入のあとの.が最初の入力と同じであることを示しています。

$ jq -c -n '42 | (. * 2) as $double | [., $double]'
[42,84]

変数のスコープ

変数のスコープは「レキシカル」です。その変数は、パイプラインの残りの部分で有効になります。 関数の中で定義された変数(関数については後で扱います)は、その関数に「ローカル」です。

変数名

変数名は$で始まる必要があります。 変数名の残りの部分は識別子です。識別子は、文字またはアンダースコアで始まり、そのあとに文字、数字、アンダースコアが続きます。

分割代入

マニュアルにはこう書かれています。

単一のas式で複数の変数を宣言できます。その際、_入力の構造に一致する_パターンを指定します(これは「分割代入」として知られています)。

例:

[1, 2, 3] as [$a, $b, $c]
| [$a, $b, $c]     # => [1, 2, 3]
{"foo": "bar", "len": [10, 20]} as {foo: $f, len: [$h, $w]}
| [$f, $h, $w]     # => ["bar", 10, 20]

変数名を_オブジェクトのキー_に一致させると、省略して書くことができます。

{"x": 4, "y": 7} as {$x, $y}
| [$x, $y]         # => [4, 7]
{"foo": "bar", "len": [10, 20]} as {$foo, $len}
| [$foo, $len]     # => ["bar", [10, 20]]
Note

同じ省略のしかたは、_オブジェクトの構築_でも逆向きに使えます。

4 as $x | 7 as $y | {$x, $y}    # => {"x":4, "y": 7}

定数

上の例で見たように、変数は定数を保存するのに便利です。 コードの中に「マジックナンバー」が現れるより、定数には名前を付けたほうがよいでしょう。

変数が不要なことも多い

変数を省略したほうが読みやすくなることもよくあります。

数値のリストの平均を計算することを考えてみましょう。

[2, 4, 8, 7]
| add as $sum
| length as $len
| $sum / $len

次の書き方と比べてみましょう。

[2, 4, 8, 7] | add / length

これは、jqの最も強力な特徴のひとつを浮き彫りにします。フィルターへの入力は、_すべての_部分式に渡されるのです。

  • 入力の配列[2,4,8,7]がaddに渡されます(addは、すべての要素に+演算子を適用して数値を合計します)
  • 同時に、[2,4,8,7]はlengthにも渡されます
  • これらの部分式が完了すると、その結果が除算され、入力の配列にある数値の平均値が返されます。

学習用の演習で必要になるjqの演算子

代替演算子://

式a // bは、aがfalseまたはnullならbを出力し、そうでなければaを出力します。 変数を設定する場面では、これはデフォルト値を用意するのにとても便利です。

(.input.theAnswer // 42) as $answer | ...
算術演算子
  • +、-、*は、通常の数値の加算、減算、乗算の演算子です。

説明

この演習では、お気に入りの料理本の絶品ラザニア作りに役立つコードを書いていきます。

タスクは4つあり、どれもラザニアを作るのにかかる時間に関するものです。

1. 想定されるオーブン時間(分)を定義する

$expected_minutes_in_ovenという名前の定数を定義します。 料理本によると、想定されるオーブン時間は40分です。

$ jq -n -f lasagna.jq
{
  "expected_minutes_in_oven": 40,
  ...

2. 残りのオーブン時間(分)を計算する

この値は、ラザニアをオーブンに入れてからの実際の経過時間(分)を入力として受け取り、前のタスクで定義した想定オーブン時間(分)をもとに、ラザニアをあと何分オーブンに入れておく必要があるかを返します。

$ echo '{"actual_minutes_in_oven": 18}' | jq -f lasagna.jq
{
  "expected_minutes_in_oven": 40,
  "remaining_minutes_in_oven": 22,
  ...

3. 準備時間(分)を計算する

準備時間とは、ラザニアをオーブンに入れる前に準備を整えるのにかかる時間です。 1層の準備には2分かかります。

$ echo '{"number_of_layers": 3}' | jq -f lasagna.jq
{
  ...
  "preparation_time": 6,
  ...

4. 合計の作業時間(分)を計算する

ラザニア作りに合計何分かけたかを計算します。 これは、準備時間(分)と、現時点でラザニアがオーブンに入っている時間(分)を足したものです。

$ echo '{"actual_minutes_in_oven": 10, "number_of_layers": 2}' | jq -f lasagna.jq
{
  ...
  "total_time": 14,
  ...
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
jq Exercism

ラザニアを始める準備はできましたか?

Exercismに登録すれば、12個のコンセプト75個の演習、そして本物の人間によるメンタリングとともに、jqを学んでマスターできます。すべて無料です。