jq 프로그램은 _표현식의 파이프라인_이라는 점을 기억해요.
변수 할당은 다음 규칙을 따라요. _변수 할당_은 다음과 같은 형태의 표현식이에요.
... | expr as $varname | ...
항등 표현식 .과 마찬가지로, _변수 할당_의 출력은 입력과 같아요.
변수 값을 설정하는 것은 부수 효과예요.
다음 예시는 할당 뒤의 .이 처음 입력과 같다는 것을 보여줘요.
$ jq -c -n '42 | (. * 2) as $double | [., $double]'
[42,84]
변수의 스코프는 "렉시컬"해요. 즉, 변수는 파이프라인의 나머지 부분에서 스코프에 들어가요. 함수 안에서 정의된 변수는 (함수는 나중에 다뤄요) 그 함수 안에서만 유효한 "지역" 변수예요.
변수는 $로 시작해야 해요.
변수 이름의 나머지 부분은 식별자예요. 문자나 밑줄로 시작하고, 그 뒤에 문자, 숫자, 밑줄이 와요.
jq 매뉴얼에는 이렇게 나와 있어요.
하나의
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]]
같은 요령이 _객체 생성_에서는 반대 방향으로도 통해요.
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 | ...
+, -, *는 각각 숫자 덧셈, 뺄셈, 곱셈을 하는 일반적인 연산자예요.이 연습 문제에서는 좋아하는 요리책을 보고 멋진 라자냐를 만들 수 있도록 도와주는 코드를 작성해요.
라자냐를 요리하는 데 걸리는 시간과 관련된 네 개의 과제가 있어요.
$expected_minutes_in_oven이라는 상수를 정의해요.
요리책에 따르면 오븐의 예상 시간(분)은 40분이에요:
$ jq -n -f lasagna.jq
{
"expected_minutes_in_oven": 40,
...
이 값은 라자냐가 오븐에 들어간 실제 시간(분)을 입력으로 받아요. 그리고 이전 과제에서 구한 오븐의 예상 시간(분)을 기준으로, 라자냐가 오븐에 더 있어야 하는 시간(분)을 반환해요.
$ echo '{"actual_minutes_in_oven": 18}' | jq -f lasagna.jq
{
"expected_minutes_in_oven": 40,
"remaining_minutes_in_oven": 22,
...
준비 시간은 라자냐를 오븐에 넣기 전에 준비하는 데 걸리는 시간이에요. 층 하나를 준비하는 데 2분이 걸려요.
$ echo '{"number_of_layers": 3}' | jq -f lasagna.jq
{
...
"preparation_time": 6,
...
라자냐를 요리하는 데 총 몇 분을 일했는지 계산해요. 이것은 준비 시간(분)과 현재까지 라자냐가 오븐에서 보낸 시간(분)의 합이에요.
$ echo '{"actual_minutes_in_oven": 10, "number_of_layers": 2}' | jq -f lasagna.jq
{
...
"total_time": 14,
...