linux json parser, jq 사용
업무상 Access token
을 확인할 일이 생겨서 curl
로 응답을 보다보니 json
응답이 가독 성이 떨어져서 parser
를 찾게 되었다.
복붙에 가까운 포스팅이 의미가 있는걸까? 기록이랍시고 남기긴하는데…
jq
는 c 언어로 작성되었다고 한다. 설치하는 방법은 두가지가 있다.
1. 귀찮으니 패키지 매니져로
#install
$ yum install jq
#install check
$ jq --version
jq-1.5
2. 원하는 배포판 다운로드/설치
#download (32-bit system)
$ wget http://stedolan.github.io/jq/download/linux32/jq
#download (64-bit system)
$ wget http://stedolan.github.io/jq/download/linux64/jq
# 권한
$ sudo chmod +x ./jq
# 실행을 위해 이동
$ sudo cp jq /usr/bin
#install check
$ jq --version
jq-1.5
options
--raw-output / -r
결과를 파싱하지않고 string 형태로 내보낸다. jq 결과값을 인자로 뭔가할때 유용하다.
file : jsondata : 예제를 위한 데이터
cat << EOL > test.json
{
"data": {
"app_id": "123",
"type": "USER",
"application": "ddd",
"data_access_expires_at": 1578986473,
"expires_at": 0,
"is_valid": true,
"issued_at": 567,
"scopes": [
"email",
"pages_show_list",
"public_profile"
],
"granular_scopes": [
{
"scope": "pages_show_list"
}
],
"user_id": "873",
"user_id>" : "873>",
"types" : [
{ "id": "user123", "name": "USER"},
{ "id": "admin098", "name": "ADMIN"},
{ "id": "guest567", "name": "GUEST"}
]
}
}
EOL
Identity .
input 을 바꾸지않고 output 으로 생산한다.
$ cat jsondata | jq '.'
{
"data": {
"app_id": "123",
"type": "USER",
"application": "ddd",
"data_access_expires_at": 1578986473,
"expires_at": 0,
"is_valid": true,
"issued_at": 567,
"scopes": [
"email",
"pages_show_list",
"public_profile"
],
"granular_scopes": [
{
"scope": "pages_show_list"
}
],
"user_id": "873",
"user_id>": "873>",
"types": [
{
"id": "user123",
"name": "USER"
},
{
"id": "admin098",
"name": "ADMIN"
},
{
"id": "guest567",
"name": "GUEST"
}
]
}
}
파싱되어 보기 편하게 된다.
여러 필터가 있는데, 간단하게 사용법만 알아봐야겠다. 공식문서를 보니 생각보다 장황하구만.
Object Identifier-Index: .foo
, .foo.bar
$ cat jsondata | jq '.data.user_id'
"873"
Generic Object Index: .[<string>]
키값에 특수문자가 존재할 때는 .somekey.someotherkey>
로 뽑을 수 없다.
$ cat jsondata | jq '.data["user_id>"]'
"873>"
Pipe: |
내부 파이프라인 |
도 지원한다
$ cat jsondata | jq '.data | .user_id'
"873"
$ cat jsondata | jq '.data' | jq '.user_id'
"873"
Array/Object Value Iterator: .[]
배열을 벗기고, 배열 값만큼 출력을 생성한다.
아래에 각각 보이는 배열값들 하나의 출력값처럼 보이지만 각각의 출력을 jq 가 만든 것이다.
$ cat jsondata | jq '.data.scopes[]'
"email"
"pages_show_list"
"public_profile"
$ cat jsondata | jq '.data.types'
[
{
"id": "user123",
"name": "USER"
},
{
"id": "admin098",
"name": "ADMIN"
},
{
"id": "guest567",
"name": "GUEST"
}
]
각각 출력인 것을 배열로 싸면 각각 출력인 것을 확인할 수도 있다.
$ cat jsondata | jq '.data.scopes[]' | jq '[.]'
[
"email"
]
[
"pages_show_list"
]
[
"public_profile"
]
각각의 출력값에서 각각 필터를 적용해서 데이터를 뽑을 수도 있다.
$ cat jsondata | jq '.data.types[].id'
"user123"
"admin098"
"guest567"
뽑은 데이터를 다시 배열로 합칠 수도있다.
$ cat jsondata | jq '[.data.types[].id]'
[
"user123",
"admin098",
"guest567"
]
합쳐진 배열은 인덱스로 접근가능하다
$ cat jsondata | jq '[.data.types[].id][0]'
"user123"
length
라는 함수도 지원한다
$ cat jsondata | jq '[.data.types[].id][0] | length'
7
$ cat jsondata | jq '[.data.types[].id] | length'
3
Comma: ,
,
를 사용하면 ,
로 나누어진 필터들로 만든 결과들만큼 출력을 만든다.
$ cat jsondata | jq '.data.scopes'
[
"email",
"pages_show_list",
"public_profile"
]
$ cat jsondata | jq '.data.scopes' | jq '.[0], .[1], .[2], .[]'
"email"
"pages_show_list"
"public_profile"
"email"
"pages_show_list"
"public_profile"
파이프라인으로 배열로 감싸보면 알기 쉽다.
$ cat jsondata | jq '.data.scopes' | jq '.[0], .[1], .[2], .[]' | jq '[.]'
[
"email"
]
[
"pages_show_list"
]
[
"public_profile"
]
[
"email"
]
[
"pages_show_list"
]
[
"public_profile"
]
나누어진 결과를 배열로 합칠 수도 있다.
$ cat jsondata | jq '.data.scopes' | jq '[.[0], .[1], .[2], .[]]'
[
"email",
"pages_show_list",
"public_profile",
"email",
"pages_show_list",
"public_profile"
]
이것외에도 filter 로 나온 값을 변경한다던지, 값을 체크한다는 기능들이 많은데 공식문서가 잘 나와있다.
select
이 함수는 aws cli 를 사용하면서 알게 되었는데, tag 의 key, value 가 특정 값인 id 를 뽑을 때 사용했다.
$ jq '.Reservations[].Instances[] | select(.Tags[]?.Key == "Name" and .Tags[]?.Value == "ec2-docker-postgresql") | .InstanceId'
$ jq '.[] | select(.name =="search-my-name")'
$ cat test.json | jq '.data.types[] | select (.name == "GUEST")'
$ jq '.[] | select(.bucket_name == "my-bucket") | .object_info.Key | select(.[length-3:] != "png")'
출처