jq!
jq
커맨드라인 JSON 프로세서 jq
json
데이터를 쉽게 조작할 수 있는 CLI 유틸리티
brew install jq
kubectl get nodes -o json
{
"items": [
{
"status": {
"addresses": [
{
"address": "192.168.65.3",
"type": "InternalIP"
},
{
"address": "docker-desktop",
"type": "Hostname"
}
]
}
}
]
}
위 명령어 수행시 아래와 같은 json
데이터가 출력될 경우
파이프라인을 묶어 아래처럼 검색식으로 사용 가능하다.
kubectl get nodes -o json | jq -r '.items[].status.addresses[] | select(.type=="InternalIP") | .address'
192.168.65.3
JSON 안 items
배열 안의 status
객체의 addresses
배열 중 type
이 InternalIP
객체 중 address
객체를 출력
jq 옵션
–raw-output / -r
jq 로 문자열 출력시 쌍따옴표로 감싸진 문자열이 출력되는데
-r
옵션을 사용하면 이 쌍따옴표를 지운다.
// test.json
[
{
"address": "192.168.65.3",
"type": "InternalIP"
},
{
"address": "docker-desktop",
"type": "Hostname"
}
]
cat test.json | jq '.[].address'
"192.168.65.3"
"docker-desktop"
cat test.json | jq -r '.[].address'
192.168.65.3
docker-desktop
–compact-output / -c
한줄로 출력하는 옵션
cat test.json | jq -c '.'
[{"address":"192.168.65.3","type":"InternalIP"},{"address":"docker-desktop","type":"Hostname"}]
–sort-keys / -S
key 를 기준으로 정렬
// sort.json
{
"b": { "address": "192.168.65.3", "type": "InternalIP" },
"a": { "address": "docker-desktop", "type": "Hostname"},
"c": { "address": "8.8.8.8", "type": "DNS" }
}
cat sort.json | jq -S '.'
{
"a": {
"address": "docker-desktop",
"type": "Hostname"
},
"b": {
"address": "192.168.65.3",
"type": "InternalIP"
},
"c": {
"address": "8.8.8.8",
"type": "DNS"
}
}
jq 내장함수
length
입력 받은 객체에 따라 길이를 반환함
// length.json
[
{
"address": "docker-desktop",
"type": "Hostname"
},
{
"address": "192.168.65.3",
"type": "InternalIP"
},
{
"address": "8.8.8.8",
"type": "DNS"
}
]
cat length.json | jq 'length'
3
cat length.json | jq '.[] | length'
2
2
2
sort_by
전체 배열을 받아 객체의 매개변수에 정의된 field 를 기반으로 정렬
// sort_by.json
[
{ "name": "aaa", "age": 23 },
{ "name": "ccc", "age": 23 },
{ "name": "bbb", "age": 23 }
]
cat sort_by.json | jq -c 'sort_by(.name)'
[{"name":"aaa","age":23},{"name":"bbb","age":23},{"name":"ccc","age":23}]
map
java8 stream 의 map 같은 역할, 변환기와 같은 역할이다.
map(x)
와 [.[] | x]
는 같은 연산이라 할 수 있다.
// map.json
[{"name":"c1","age":23},{"name":"h2","age":33},{"name":"h3","age":36}]
cat map.json | jq -c 'map(.age) '
[23,33,36]
cat map.json | jq -c 'map(.age+1)'
[24,34,37]
cat map.json | jq -c '[ .[] | .age ]'
[23,33,36]
cat test.json | jq -c 'map(.age > 30)'
[false,true,true]
객체도 map 함수 입력값이 될 수 있으며 value 값을 순회한다.
echo '{"a":1,"b":2,"c":3}' | jq -c 'map(.+1)'
[2,3,4]
select
boolean_expression 조건문을 이용해 원하는 속성만 출력
[{
"name": "c1",
"age": 23
}, {
"name": "h2",
"age": 33
}, {
"name": "h3",
"age": 36
}]
cat test.json | jq '.[] | select(.age > 30)'
{
"name": "h2",
"age": 33
}
{
"name": "h3",
"age": 36
}
배열형태의 데이터가 아니기 때문에 map
함수를 사용해 변환하여 배열로 내보낼 수 있다.
cat test.json | jq 'map(select(.age > 30))'
[
{
"name": "h2",
"age": 33
},
{
"name": "h3",
"age": 36
}
]
그냥 마지막에 배열로 감싸도 된다.
cat test.json | jq '[ .[] | select(.age > 30)]'
[
{
"name": "h2",
"age": 33
},
{
"name": "h3",
"age": 36
}
]
to_entries
key-value 형식으로 데이터를 변경함,
// to_entries.json
[
{ "name": "aaa", "age": 23 },
{ "name": "ccc", "age": 23 },
{ "name": "bbb", "age": 23 }
]
cat to_entries.json | jq 'to_entries'
[
{
"key": 0,
"value": {
"name": "aaa",
"age": 23
}
},
{
"key": 1,
"value": {
"name": "ccc",
"age": 23
}
},
{
"key": 2,
"value": {
"name": "bbb",
"age": 23
}
}
]
{
"A": { "name": "aaa", "age": 23 },
"B": { "name": "ccc", "age": 23 },
"C": { "name": "bbb", "age": 23 }
}
cat test.json | jq 'to_entries'
[
{
"key": "A",
"value": {
"name": "aaa",
"age": 23
}
},
{
"key": "B",
"value": {
"name": "ccc",
"age": 23
}
},
{
"key": "C",
"value": {
"name": "bbb",
"age": 23
}
}
]
assignment
|= Update-assignment
update
연산자라 할 수 있다.
echo '{"a":1,"b":2,"c":3}' | jq -c '.[] |= .+1'
{"a":2,"b":3,"c":4}