jq에 JSON 데이터를 입력하는 방법
jq는 입력을 처리하는 기능을 가지고 있습니다. 입력을 어떻게 처리할 지에 대한 정보를 첫 번째 인자로 받습니다. 이 인자는 jq 고유의 문법으로 작성됩니다. 점(.)은 동일값Identity 필터입니다. 입력받은 내용을 그대로 출력하라는 의미를 가지고 있습니다. 이를 인자로 넘겨 실행해보겠습니다.
$ jq '.'
명령어를 실행하면 jq로 제어권이 넘어가고 아무일도 일어나지 않습니다. jq는 입력을 기다리고 있습니다. {"foo": "bar"}를 입력해봅니다.
$ jq '.'
{"foo": "bar"}
{
"foo": "bar"
}
{"foo": "bar"} 을 입력하면 입력받은 내용을 가다듬어서 출력해줍니다. 이와 같이 jq를 실행하고 데이터를 직접 입력하는 게 첫 번째 입력방법입니다. 이 때 입력받은 내용을 그대로 출력하는 것은 아니고 JSON 데이터 구조를 파싱해서 저장한 다음 다시 출력하는 방식이라서 원래의 입력이 복원되지는 않습니다.
두 번째 방법은 파일을 지정하는 방법입니다. 다음과 같이 JSON 데이터를 foobar.json에 저장하고, jq의 두 번째 인자로 넘겨줍니다. 결과는 첫 번째 입력 방식과 같습니다.
$ echo '{"foo": "bar"}' > foobar.json
$ jq '.' foobar.json
{
"foo": "bar"
}
세 번째 방법은 파이프 연산자로 다른 프로세스의 출력을 넘겨받아 jq의 입력으로 보내는 방법입니다.
$ echo '{"foo": "bar"}' | jq '.'
{
"foo": "bar"
}
파이프를 사용하는 방법은 특히 강력합니다. 일례로 웹API에서 반환받은 JSON 데이터를 별도로의 과정을 거치지 않고 곧바로 처리할 수 있습니다. 깃헙Github API를 호출한 결과를 jq에 넘겨보겠습니다.
$ curl -s 'https://api.github.com/users/octocat' | jq '.'
{
"login": "octocat",
"id": 583231,
...
이 글에서도 주로 파이프를 사용해서 입력을 전달합니다. jq를 사용하는 가장 일반적인 패턴이니 꼭 익혀두시기 바랍니다.
동일값Identity 필터를 사용한 JSON 정형화
jq의 가장 기본적인 활용법은 JSON 데이터를 정형화해서 출력하는 일입니다. 코드의 정형화를 프리티 프린트Pretty Print라고 부르기도 합니다. JSON은 스펙상 의미있는 문자열 사이에 공백문자나 개행이 들어갈 수 있습니다. 따라서 의미가 완벽히 같은 서로 다른 JSON 문서가 존재할 수 있습니다. 예를 들어 {"foo" : "bar"}와 { "foo" : "bar" }는 완전히 같은 의미를 가진 서로 다른 JSON 문서입니다. jq는 이를 사람이 보기 좋게 정형화하고, 의미가 같다면 같은 구조로 출력해줍니다. 정형화를 위해 동일값 필터(.)을 사용할 수 있습니다.
$ echo '{"foo" : "bar"}' | jq '.'
{
"foo": "bar"
}
$ echo '{ "foo" : "bar" }' | jq '.'
{
"foo": "bar"
}
기계 입장에서 이러한 변형에 특별한 의미가 있지는 않습니다. 위에서 예로 든 두 데이터와 jq의 출력 결과는 모두 같은 의미를 가지고 있습니다. 프로그래밍 언어나 jq 입장에서는 이를 파싱하고 나면 결국 같은 구조와 의미를 가지고 있습니다. 이러한 변형을 하는 가장 큰 이유는 사람이 직접 데이터를 읽기 위해서입니다.
특히 JSON 데이터가 한 줄로 기록되어있거나 공백문자가 전부 제거된 경우 사람이 읽는 것은 매우 어렵습니다. 예를 들어 다음과 같은 데이터가 있다고 가정해봅니다. 이 정도는 아주 복잡한 데이터는 아닙니다만, 한 눈에 잘 들어오지 않습니다.
{"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"NetworkID":"6d583450be96208b0",
"EndpointID":"d6138701512082a8d3","Gateway":"172.17.0.1","IPAddress":"172.17.0.2",
"IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,
"MacAddress":"02:55:ac:11:00:02","DriverOpts":null}}
이 JSON 데이터를 jq에 넘겨주면 다음과 같이 예쁘게 출력해줍니다.
{
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "6d583450be96208b0",
"EndpointID": "d6138701512082a8d3",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:55:ac:11:00:02",
"DriverOpts": null
}
}
jq는 JSON 데이터를 다루는 강력한 기능들을 가지고 있지만 단순히 정형화 용도로도 자주 사용됩니다. 일반적인 활용법이므로 | jq '.'를 관용구로 외워두면 편리합니다.
노트
파이썬으로 JSON 정형화
jq가 없고 파이썬만 있는 환경에서는 다음 명령어로 JSON 데이터를 정형화할 수 있습니다.
$ echo '{ "foo" : "bar" }' | python -mjson.tool
{
"foo": "bar"
}
단일 입력 단일 출력을 다루는 jq 문법 기초
이미 살펴보았듯이 jq는 첫 번째 인자로 jq 고유의 문법으로 이루어진 값을 넘겨받습니다. 지금까지는 동일값 필터(.)만 사용했습니다. 이것만 알아도 jq는 유용합니다. 하지만 jq 문법을 조금만 알아도 활용 범위는 훨씬 더 넓어집니다. 여기서부터는 jq에서 데이터를 추출하거나 간단히 변형하는 방법에 대해서 알아보겠습니다.
jq는 JSON 데이터를 입력 받아 JSON을 출력한다
일반적으로 JSON 데이터는 루트 엘리먼트가 배열이나 객체로 이루어져있습니다. 하지만 JSON 스펙상 루트 엘리먼트가 배열이나 객체일 이유는 없습니다. 이해를 위해 가장 간단한 원시적 타입(null, 문자열, 숫자)으로만 이루어진 JSON부터 생각해보겠습니다.
$ echo 'null' | jq '.'
null
$ echo '"String"' | jq '.'
"String"
$ echo '44' | jq '.'
44
이는 그저 입력받은 JSON 데이터를 다시 출력하는 간단한 명령입니다. 하지만 여기서 중요한 단서가 있습니다. jq가 출력하는 결과는 유효한 JSON 문서라는 점입니다. null, "String", 44는 모두 유효한 JSON 데이터입니다. 예를 들어서 "로 감싸지 않은 문자열을 직접 넘겨주면 jq는 이를 제대로 처리하지 못 합니다.
$ echo 'String' | jq '.'
parse error: Invalid numeric literal at line 2, column 0
String은 올바른 JSON 표현이 아니기 때문입니다. jq가 JSON 데이터를 입력받아 JSON 데이터를 출력한다는 것을 기억하시기 바랍니다. 뒤에서 더 자세히 다루겠지만 jq의 동작 방식을 이해하기 위해서는 이 점을 반드시 기억해야합니다.
노트
홑따옴표 사용하기
셸 위에서 따옴표 해석은 자주 헷갈리는 부분 중 하나입니다. jq를 사용할 때는 잘못 해석되는 것을 방지하기 위해서 echo나 jq의 인자를 반드시 홑따옴표(')로 감싸는 것을 추천합니다. 셸에서 홑따옴표 안의 문자열은 변형되지 않고 거의 그대로 이용됩니다. 예를 들어 JSON 문자열을 만들고자 할 때 'String', "String"는 모두 의도한 대로 동작하지 않습니다. '"String"'와 같이 홑따옴표 안에서 다시 쌍따옴표로 감싸야만 JSON 문자열로 해석됩니다.
참고 : https://www.44bits.io/ko/post/cli_json_processor_jq_basic_syntax\
커맨드라인 JSON 프로세서 jq : 기초 문법과 작동원리
jq는 커맨드 라인 JSON 프로세서입니다. JSON 데이터를 입력받아 데이터를 필터링하거나 변형합니다. jq의 기본적인 문법과 작동 원리를 소개합니다.
www.44bits.io
AWS 인스턴스의 특정 Tag:Value 값을 변수로 받아서 처리하는 작업에 사용
ex
aws cli를 통해 SageMaker 노트북의 특정 태그 값을 읽고 jq를 통해 그 값과 동일한 이름의py파일을 기동 시키는 스크립트
SH=`aws sagemaker list-tags --resource-arn arn주소 | jq --raw-output '.Tags[]| select(.Key=="태그").Value'`
if [ $SH == yes ]; then
echo normal boot
else
python3 $SH.py &
fi
'Shell' 카테고리의 다른 글
System Log Daily Archiving (0) | 2023.09.04 |
---|---|
로그 관련 (0) | 2023.02.24 |