jq & yq Command Cheat Sheet
JSON과 YAML 데이터를 처리하는 도구인 jq와 yq사용하며 알게된 CLI 명령어들을 공유합니다.
jq 기본 사용법
1
2
3
4
5
6
7
8
9
10
11
12
13
# 기본 구조
jq '.' file.json # JSON 파일 예쁘게 출력
jq '.' <<< '{"name":"John","age":30}' # 문자열에서 JSON 파싱
echo '{"name":"John","age":30}' | jq '.' # 파이프로 JSON 처리
curl -s https://api.github.com/users/octocat | jq '.' # API 응답 파싱
# 기본 필터링
jq '.name' file.json # 특정 키 값 추출
jq '.user.name' file.json # 중첩된 객체 접근
jq '.users[0]' file.json # 배열 첫 번째 요소
jq '.users[0].name' file.json # 배열 요소의 속성
jq '.users[]' file.json # 배열의 모든 요소
jq '.users[].name' file.json # 배열 모든 요소의 name 속성
jq 고급 필터링 및 선택
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 조건부 필터링
jq '.users[] | select(.age > 25)' file.json # 조건에 맞는 요소만 선택
jq '.users[] | select(.name == "John")' file.json # 특정 값과 일치하는 요소
jq '.users[] | select(.active == true)' file.json # boolean 값으로 필터링
jq '.users[] | select(.tags | contains(["admin"]))' file.json # 배열에 특정 값 포함
# 배열 슬라이싱
jq '.users[1:3]' file.json # 인덱스 1부터 2까지
jq '.users[:3]' file.json # 처음부터 인덱스 2까지
jq '.users[2:]' file.json # 인덱스 2부터 끝까지
jq '.users[-2:]' file.json # 뒤에서 2번째부터 끝까지
# 키 존재 여부 확인
jq '.users[] | select(has("email"))' file.json # email 키가 있는 요소만
jq '.users[] | select(.email != null)' file.json # email 값이 null이 아닌 요소
jq 'has("users")' file.json # 최상위에 users 키 존재 여부
jq 데이터 변환 및 조작
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 객체 생성 및 변환
jq '.users[] | {name: .name, email: .email}' file.json # 새로운 객체 생성
jq '.users[] | {fullName: (.firstName + " " + .lastName)}' file.json # 문자열 연결
jq '.users[] | {name, age}' file.json # 축약 문법 (키와 값이 같을 때)
jq '{userCount: (.users | length), users: .users}' file.json # 계산된 값 포함
# 배열 변환
jq '.users | map(.name)' file.json # 배열의 각 요소를 name으로 변환
jq '.users | map(select(.age > 25))' file.json # 조건에 맞는 요소만 매핑
jq '.users | map({name, isAdult: (.age >= 18)})' file.json # 계산된 속성 추가
# 그룹화 및 집계
jq '.users | group_by(.department)' file.json # 부서별 그룹화
jq '.users | group_by(.age) | map({age: .[0].age, count: length})' file.json # 나이별 개수
jq '.users | map(.age) | add / length' file.json # 평균 나이 계산
jq '.users | map(.salary) | max' file.json # 최대 급여
jq '.users | map(.salary) | min' file.json # 최소 급여
jq 경로 탐색 및 키 조작
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 모든 경로 탐색
jq 'paths' file.json # 모든 경로 배열로 출력
jq 'paths | join(".")' file.json # 경로를 점 표기법으로 연결
jq 'paths(scalars)' file.json # 스칼라 값의 경로만
jq 'paths(objects)' file.json # 객체의 경로만
jq 'paths(arrays)' file.json # 배열의 경로만
# 키 조작
jq 'keys' file.json # 모든 키 목록
jq 'keys_unsorted' file.json # 정렬되지 않은 키 목록
jq '.users[0] | keys' file.json # 특정 객체의 키들
jq 'to_entries' file.json # 키-값 쌍을 배열로 변환
jq 'to_entries | map(select(.key | startswith("user")))' file.json # 특정 접두사 키만
# 재귀적 탐색
jq '.. | objects | select(has("name"))' file.json # name 키를 가진 모든 객체
jq '.. | select(type == "string")' file.json # 모든 문자열 값
jq '.. | select(type == "number")' file.json # 모든 숫자 값
jq 문자열 및 타입 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 문자열 조작
jq '.users[].name | ascii_downcase' file.json # 소문자 변환
jq '.users[].name | ascii_upcase' file.json # 대문자 변환
jq '.users[].email | split("@")[0]' file.json # 이메일에서 사용자명 추출
jq '.users[].name | length' file.json # 문자열 길이
jq '.description | gsub("old"; "new")' file.json # 문자열 치환
# 타입 확인 및 변환
jq '.users[] | type' file.json # 각 요소의 타입
jq '.age | tostring' file.json # 숫자를 문자열로
jq '.ageString | tonumber' file.json # 문자열을 숫자로
jq '.users | length' file.json # 배열 길이
jq '. | type' file.json # 루트 객체 타입
# 날짜 및 시간 처리
jq '.timestamp | strftime("%Y-%m-%d %H:%M:%S")' file.json # Unix 타임스탬프 포맷
jq '.dateString | strptime("%Y-%m-%d") | mktime' file.json # 문자열을 Unix 타임스탬프로
jq 'now' file.json # 현재 Unix 타임스탬프
jq 고급 기능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 조건문 및 논리 연산
jq '.users[] | if .age >= 18 then "adult" else "minor" end' file.json # 조건문
jq '.users[] | select(.active and .verified)' file.json # AND 조건
jq '.users[] | select(.role == "admin" or .role == "moderator")' file.json # OR 조건
jq '.users[] | select(.age >= 18 and .department == "IT")' file.json # 복합 조건
# 에러 처리
jq '.users[]?.email // "No email"' file.json # null 값에 대한 기본값
jq '.users[] | .email // empty' file.json # null 값 제거
jq 'try .nonexistent.field catch "Field not found"' file.json # 에러 처리
# 변수 사용
jq --arg name "John" '.users[] | select(.name == $name)' file.json # 외부 변수 사용
jq --argjson age 25 '.users[] | select(.age > $age)' file.json # JSON 변수 사용
jq '.users as $users | $users | length' file.json # 내부 변수 정의
# 함수 정의
jq 'def isAdult: .age >= 18; .users[] | select(isAdult)' file.json # 사용자 정의 함수
yq 기본 사용법
1
2
3
4
5
6
7
8
9
10
11
# 기본 구조 (yq v4 기준)
yq '.' file.yaml # YAML 파일 예쁘게 출력
yq eval '.' file.yaml # 명시적 eval 사용
yq -o json '.' file.yaml # YAML을 JSON으로 변환
yq -P '.' file.json # JSON을 YAML로 변환
# 기본 필터링
yq '.name' file.yaml # 특정 키 값 추출
yq '.spec.containers[0].image' file.yaml # 중첩된 값 접근
yq '.items[]' file.yaml # 배열의 모든 요소
yq '.items[].metadata.name' file.yaml # 배열 요소의 속성
yq 고급 필터링 및 선택
1
2
3
4
5
6
7
8
9
10
# 조건부 필터링
yq '.items[] | select(.kind == "Pod")' file.yaml # 조건에 맞는 요소만
yq '.spec.containers[] | select(.name == "nginx")' file.yaml # 특정 컨테이너만
yq '.items[] | select(.metadata.labels.app == "web")' file.yaml # 라벨로 필터링
# 배열 조작
yq '.items | length' file.yaml # 배열 길이
yq '.items[0:2]' file.yaml # 배열 슬라이싱
yq '.items | sort_by(.metadata.name)' file.yaml # 정렬
yq '.items | reverse' file.yaml # 역순 정렬
yq 경로 탐색 및 키 조작
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 모든 경로 탐색
yq 'paths' file.yaml # 모든 경로 배열로 출력
yq 'paths | join(".")' file.yaml # 경로를 점 표기법으로 연결
yq 'paths(scalars)' file.yaml # 스칼라 값의 경로만
yq '.. | path | join(".")' file.yaml # 모든 노드의 경로
# 키 조작
yq 'keys' file.yaml # 모든 키 목록
yq '.metadata | keys' file.yaml # 특정 객체의 키들
yq 'to_entries' file.yaml # 키-값 쌍을 배열로 변환
yq 'with_entries(select(.key | startswith("app")))' file.yaml # 특정 접두사 키만
# 재귀적 탐색
yq '.. | select(tag == "!!str")' file.yaml # 모든 문자열 값
yq '.. | select(type == "!!int")' file.yaml # 모든 정수 값
yq '.. | select(has("name"))' file.yaml # name 키를 가진 모든 객체
yq 데이터 변환 및 수정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 값 수정
yq '.spec.replicas = 3' file.yaml # 값 변경
yq '.metadata.labels.version = "v2.0"' file.yaml # 새 라벨 추가
yq 'del(.spec.template.spec.nodeSelector)' file.yaml # 키 삭제
yq '.spec.containers[0].image = "nginx:1.20"' file.yaml # 배열 요소 수정
# 객체 생성 및 병합
yq '.metadata.labels += {"environment": "production"}' file.yaml # 객체 병합
yq '. * {"spec": {"replicas": 5}}' file.yaml # 깊은 병합
yq 'select(.kind == "Deployment") | .spec.replicas = 3' file.yaml # 조건부 수정
# 배열 조작
yq '.spec.containers += [{"name": "sidecar", "image": "busybox"}]' file.yaml # 배열에 요소 추가
yq '.spec.containers |= map(select(.name != "old-container"))' file.yaml # 배열에서 요소 제거
yq '.spec.containers |= sort_by(.name)' file.yaml # 배열 정렬
yq 다중 문서 처리
1
2
3
4
5
6
7
8
# 다중 YAML 문서
yq 'select(.kind == "Deployment")' multi-doc.yaml # 특정 종류 문서만 선택
yq 'select(document_index == 0)' multi-doc.yaml # 첫 번째 문서만
yq '. as $item ireduce ({}; . * $item)' multi-doc.yaml # 모든 문서 병합
# 파일 간 작업
yq eval-all '. as $item ireduce ({}; . * $item)' file1.yaml file2.yaml # 여러 파일 병합
yq eval-all 'select(fileIndex == 0)' file1.yaml file2.yaml # 첫 번째 파일만
실제 사용 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Kubernetes 매니페스트 처리
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase, node: .spec.nodeName}'
kubectl get deployments -o yaml | yq '.items[] | select(.spec.replicas > 1) | .metadata.name'
# AWS CLI 출력 처리
aws ec2 describe-instances | jq '.Reservations[].Instances[] | {id: .InstanceId, state: .State.Name, type: .InstanceType}'
aws eks describe-cluster --name my-cluster | jq '.cluster | {name: .name, status: .status, version: .version}'
# 설정 파일 처리
yq '.services.web.environment.DATABASE_URL = "postgresql://localhost:5432/mydb"' docker-compose.yml
jq '.scripts.start = "node server.js"' package.json
# 로그 분석
cat app.log | jq -r 'select(.level == "ERROR") | .message'
kubectl logs deployment/my-app -o json | jq -r '.log | fromjson | select(.severity == "ERROR")'
# 데이터 변환
curl -s https://api.github.com/repos/kubernetes/kubernetes/releases | jq '.[0] | {name: .name, published: .published_at, assets: [.assets[] | {name: .name, download_count: .download_count}]}'
유용한 팁과 트릭
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 컬러 출력
jq -C '.' file.json # 컬러 출력 강제
jq --color-output '.' file.json # 컬러 출력 (긴 형태)
# Raw 출력
jq -r '.users[].name' file.json # 따옴표 없이 문자열 출력
yq -r '.metadata.name' file.yaml # Raw 문자열 출력
# 압축 출력
jq -c '.' file.json # 압축된 JSON 출력
yq -o json -I=0 '.' file.yaml # 압축된 JSON 변환
# 정렬된 키
jq -S '.' file.json # 키를 알파벳순으로 정렬
yq 'sort_keys(.)' file.yaml # YAML 키 정렬
# 스트림 처리
jq --stream '.' large-file.json # 대용량 파일 스트림 처리
yq --stream '.' large-file.yaml # YAML 스트림 처리
# 에러 무시
jq -e '.' file.json # 빈 결과나 false에서 exit code 1
jq --exit-status '.' file.json # 긴 형태
궁금하신 점이나 추가해야 할 부분은 댓글이나 아래의 링크를 통해 문의해주세요.
Written with KKam._.Ji
This post is licensed under CC BY 4.0 by the author.