라자냐

라자냐

학습 연습 문제

소개

변수

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]]
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 | ...
산술 연산자
  • +, -, *는 각각 숫자 덧셈, 뺄셈, 곱셈을 하는 일반적인 연산자예요.

지침

이 연습 문제에서는 좋아하는 요리책을 보고 멋진 라자냐를 만들 수 있도록 도와주는 코드를 작성해요.

라자냐를 요리하는 데 걸리는 시간과 관련된 네 개의 과제가 있어요.

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. 준비 시간(분)을 계산해요

준비 시간은 라자냐를 오븐에 넣기 전에 준비하는 데 걸리는 시간이에요. 층 하나를 준비하는 데 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에 가입하고 jq 트랙을 개념 12개연습 문제 75개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.