jq로 조금 복잡한 검색하기
jq
명령으로 배열의 요소이고 복잡한 구조를 가진 요소(여기서는 aws ec2 describe-instances
의 결과)에 대해 검색을 해 보았습니다.소개
㈜ 주식회사 아이리지의 Common Lisp 사랑하는 서버사이드 엔지니어, tanaka.lisp입니다.
AWS EC2를 사용하는 경우 특정 인스턴스의 정보(인스턴스 ID, 인스턴스 유형 등)를 알고 싶어질 수 있습니다. 다만, 그 때문에만 관리 콘솔을 포치포치하고 취득하고 있으면, 왠지 졌던 생각이 들고(이것 소중히), 쉘 스크립트등으로 결과를 이용할 때에 불편합니다.
awscli
의 aws ec2 describe-instances
에서 얻은 결과를 jq
에 먹여 인스턴스에 붙이고 있는 이름에서 좋게 검색하고 성형하고 싶은 곳이지만, awscli
:
{
"Reservations": [
"Instances": [
{
"InstanceId": "i-commonlisp",
"Tags": [
{
"Key": "Name",
"Value": "app.commonlisp"
},
{
"Key": "aws.cloudformation:stack-name",
"Value": "stack.commonlisp"
}
],
...
},
...
],
...
]
}
여기서 이름( Tags
의 Key
이 Name
의 값)으로 인스턴스를 검색하는 방법을 시행착오했습니다.
준비하는 것
{
"Reservations": [
"Instances": [
{
"InstanceId": "i-commonlisp",
"Tags": [
{
"Key": "Name",
"Value": "app.commonlisp"
},
{
"Key": "aws.cloudformation:stack-name",
"Value": "stack.commonlisp"
}
],
...
},
...
],
...
]
}
jq
: jq-1.5-1-a5b5cbe
awscli
: aws-cli/1.11.58 Python/3.6.0 Linux/4.8.0-41-generic botocore/1.5.21
jq에서 검색
jq
에서는 입력의 JSON에 대해, 다음과 같이 할 수 있습니다:
{"id": .InstanceId, "tags": .Tags}
) select
) 이번에는 이것들을 조합해,
aws ec2 describe-instances
의 결과로부터 찾고 있는 인스턴스의 인스턴스 ID( InstanceId
)를 취득해 보겠습니다.입력 성형
예를 들어 이런 JSON 객체가 있고,
[
{
"name": "Lisp",
"developer": "John McCarthy"
},
{
"name": "Common Lisp",
"developer": "ANSI X3J13 committee",
"spec": "ANSI INCITS 226-1994 (R2004)"
},
{
"name": "Arc",
"developer": "Paul Graham",
"books": [
"On Lisp",
"Hackers and Painters"
]
},
{
"name": "Clojure",
"developer": "Rich Hicky"
}
]
언어명(
lang
)과 개발자명( developer
)만을 원할 때 입력을 printf
적으로 성형할 수 있습니다.$ echo '...上のJSON...' \
| jq '.[] | {"lang": .name, "developer": .developer}'
{
"lang": "Lisp",
"developer": "John McCarthy"
}
{
"lang": "Common Lisp",
"developer": "ANSI X3J13 committee"
}
{
"lang": "Arc",
"developer": "Paul Graham"
}
{
"lang": "Clojure",
"developer": "Rich Hicky"
}
요소를 추출하는 것처럼 보이지만, 별도로 더 추출한 오퍼레이터가 있으므로, 이쪽은
整形
라고 불렀습니다.입력에서 데이터 추출
조건을 만족하는 것만을 pass through 한다고 하는 오퍼레이터도 있어, 그것이
select
입니다. 여기를 抽出
라고 여기에서는 부르고 있습니다.man
에 있는 것이 전부입니다만, select(boolean_expression)
The function select(foo) produces its input unchanged if foo returns true for that input, and produces no output otherwise.
It´s useful for filtering lists: [1,2,3] | map(select(. >= 2)) will give you [2,3].
정규식을 조합할 수 있으므로 강력합니다;
$ echo '...上のJSON...' \
| jq '.[] | .name |select( .| test("Lisp"))'
"Lisp"
"Common Lisp"
실제로 추출
Exactly 이름으로 인스턴스 찾기
에서는 실제로 검색 쿼리를 만들어 보겠습니다.
우선 인스턴스 리스트를 얻고,
$ aws ec2 describe-instances | jq '.Reservations[].Instances[]'
{
"ImageId": "ami-commonlisp",
"State": {
"Code": 16,
"Name": "running"
}
}
{
... # ずらずら出るので省略
거기에 Tags
의 Key
의 Name
의 Value
가 Exactly app.commonlisp
의 요소만 참이 되는 조건을 더합니다 ( 루시의 파르시가 퍼지로 코쿤 느낌).
$ aws ec2 describe-instances | jq '.Reservations[].Instances[]
| select(.Tags[].Key == "Name" and .Tags[].Value == "app.commonlisp")
{
"InstanceId": "i-commonlisp",
... # ずらずら出るので省略
}
그런 다음 불필요한 요소는 나오지 않도록합시다.
$ aws ec2 describe-instances | jq '.Reservations[].Instances[]
| select(.Tags[].Key == "Name" and .Tags[].Value == "app.commonlisp")
| {"instance-id": .InstanceId, "tags": .Tags}'
{
"instance-id": "i-commonlisp",
"tags": [
{
"Key": "Name",
"Value": "app.commonlisp"
},
{
"Key": "aws:autoscaling:groupName",
"Value": "commonlisp-ApplicationFleet"
},
... # タグが出るので省略
]
}
이름 비밀 인스턴스 검색
왠지 app
라고 이름을 붙인 것 같은 생각이 들지만, 전혀 생각나지 않는다. 우리는 분위기에서 서버를 세우고 있습니다. . 그런 당신에게 바친다. 주로 나 자신에게 바치는 .
$ aws ec2 describe-instances | jq '.Reservations[].Instances[]
| select( .Tags[].Key == "Name" and (.Tags[].Value | test("^app")))
| {"instance-id": .InstanceId, "tags": .Tags}'
{
"instance-id": "i-commonlisp",
"tags": [
{
"Key": "Name",
"Value": "app.commonlisp"
},
{
"Key": "aws:autoscaling:groupName",
"Value": "commonlisp-ApplicationFleet"
},
... # タグが出るので省略
]
}
{
"instance-id": "i-clojure",
"tags": [
{
"Key": "Name",
"Value": "app.clojure"
},
{
"Key": "aws:autoscaling:groupName",
"Value": "clojure-ApplicationFleet"
},
... # タグが出るので省略
]
}
결론
jq
에서의 검색에 대해 다음을 언급했습니다.
$ aws ec2 describe-instances | jq '.Reservations[].Instances[]'
{
"ImageId": "ami-commonlisp",
"State": {
"Code": 16,
"Name": "running"
}
}
{
... # ずらずら出るので省略
$ aws ec2 describe-instances | jq '.Reservations[].Instances[]
| select(.Tags[].Key == "Name" and .Tags[].Value == "app.commonlisp")
{
"InstanceId": "i-commonlisp",
... # ずらずら出るので省略
}
$ aws ec2 describe-instances | jq '.Reservations[].Instances[]
| select(.Tags[].Key == "Name" and .Tags[].Value == "app.commonlisp")
| {"instance-id": .InstanceId, "tags": .Tags}'
{
"instance-id": "i-commonlisp",
"tags": [
{
"Key": "Name",
"Value": "app.commonlisp"
},
{
"Key": "aws:autoscaling:groupName",
"Value": "commonlisp-ApplicationFleet"
},
... # タグが出るので省略
]
}
$ aws ec2 describe-instances | jq '.Reservations[].Instances[]
| select( .Tags[].Key == "Name" and (.Tags[].Value | test("^app")))
| {"instance-id": .InstanceId, "tags": .Tags}'
{
"instance-id": "i-commonlisp",
"tags": [
{
"Key": "Name",
"Value": "app.commonlisp"
},
{
"Key": "aws:autoscaling:groupName",
"Value": "commonlisp-ApplicationFleet"
},
... # タグが出るので省略
]
}
{
"instance-id": "i-clojure",
"tags": [
{
"Key": "Name",
"Value": "app.clojure"
},
{
"Key": "aws:autoscaling:groupName",
"Value": "clojure-ApplicationFleet"
},
... # タグが出るので省略
]
}
jq
에서의 검색에 대해 다음을 언급했습니다.jq
라고 잘 생긴 DSL군요. jq 는 튜링 완전 그렇지만 것 같고, 바로 JSON 시대의 awk
감이 있습니다.그런데
jq
에서 검색 할 뿐인데 왜 기사가 길어지는지
Reference
이 문제에 관하여(jq로 조금 복잡한 검색하기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/t-sin/items/40c9fef72751de77635a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)