셸에서 JSON 구문 분석

셸에서 JSON 구문 분석

셸에서 JSON 출력을 어떻게 구문 분석할 수 있나요?

예를 들어 Amazon Web Services는 인스턴스 상태를 검색하는 CLI를 제공합니다.

$ aws ec2 describe-instances <my_instance_id>

그러나 명령은 JSON 문자열을 반환합니다. 해당 명령의 출력은 다음과 같습니다.

$ aws ec2 describe-instances x12345
{
    "Reservations" :
     {  
            "OwnerId": "1345345"
            "Groups": [], 
            "SecurityGroups": [
               {
                  "Foo" : "yes"
                  "Bar" : "no
               }
             ]
     }
}

JSON 출력을 구문 분석하는 데 사용할 수 있는 쉘 내장 기능이 있습니까?

FOO예를 들어, 다음과 같은 셸 변수를 캡처하고 싶습니다 output["Reservations"]["SecurityGroups"][0]{"Foo"}.

도움이 된다면 Zsh에서 작동할 수 있는 솔루션에 특히 관심이 있습니다.

답변1

내가 이해하는 바에 따르면 당신은 "Foo"의 가치를 찾고 있습니다. 이것은정말쉘 명령줄 도구를 사용하면 쉽습니다 jq. sed그것은 자신만의 파서 언어를 구현한다는 점에서 비슷합니다 . 귀하의 예를 들면 다음과 같습니다.

json='
{
    "Reservations" :
     {  
            "OwnerId" : "1345345",
            "Groups" :  [],
            "SecurityGroups" : [
               {
                  "Foo" : "yes",
                  "Bar" : "no"
               }
             ]
     }
}'

jqyes다음과 같이 간단하게 얻을 수 있습니다 .

printf %s "$json" |
jq '.[].SecurityGroups[0].Foo?'                                                

산출

"yes"

표기법을 사용하여 객체 해시 또는 사전 목록을 탐색할 수 있으며 .dot, 짐작할 수 있듯이 숫자, 대괄호로 묶인 인덱스를 사용하여 인덱스 배열을 더 간단하게 인덱스할 수 있습니다. 위 명령에서는 빈 인덱스 형식을 사용하여 해당 레벨의 반복 가능한 항목을 모두 확장하고 싶다는 것을 나타냅니다. 다음과 같은 방법으로 이해하는 것이 더 쉬울 수 있습니다.

printf %s "$json" | jq '.[][]'

... 해시의 두 번째 수준 항목에 대한 모든 값을 분석하여 다음을 얻습니다.

"1345345"
[]
[
  {
    "Foo": "yes",
    "Bar": "no"
  }
]

jq이는 의 기능 과 관련하여 표면을 거의 긁지 않습니다 . 이는 셸에서 데이터를 직렬화하는 매우 강력한 도구이며, 클래식 Unix 스타일로 단일 실행 가능한 바이너리로 컴파일됩니다. 배포용 패키지 관리자를 통해 사용할 수 있을 가능성이 높으며 문서도 매우 잘 정리되어 있습니다. 방문해보세요git-페이지직접 확인해 보세요.

그건 그렇고, 계층화된 데이터를 다루는 또 다른 방법은 json- 적어도 작업 중인 내용에 대한 아이디어를 얻기 위해 - 다른 방향으로 가서 표기법을 사용하여 .dot분리하는 것일 수 있습니다.모두모두다음과 같은 수준:

printf %s "$json" | jq '..'

{
  "Reservations": {
    "OwnerId": "1345345",
    "Groups": [],
    "SecurityGroups": [
      {
        "Foo": "yes",
        "Bar": "no"
      }
    ]
  }
}
{
  "OwnerId": "1345345",
  "Groups": [],
  "SecurityGroups": [
    {
      "Foo": "yes",
      "Bar": "no"
    }
  ]
}
"1345345"
[]
[
  {
    "Foo": "yes",
    "Bar": "no"
  }
]
{
  "Foo": "yes",
  "Bar": "no"
}
"yes"
"no"

jq그러나 아마도 훨씬 더 나은 방법은 다양한 유형의 노드에 대해 제공되는 많은 발견 또는 검색 방법 중 하나를 사용하는 것입니다 .

답변2

이것은 귀하의 목표에 대한 답변이지만 귀하의 질문은 아닙니다. 이는 JSON 파서를 사용하지 않고도 목표를 달성할 수 있음을 의미합니다.

AWS cli 유틸리티에는 --query인수를 사용하여 선택 필드만 출력하는 기능이 있습니다. 이것은 문서화되어 있습니다.여기.

예를 들어:

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[0].GroupName' \
  --instance-id i-6b272337 \
  --output text
mongodb

원하는 경우 여러 필드를 선택할 수도 있습니다.

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[0].[GroupName,GroupId]' \
  --instance-id i-6b272337 \
  --output text
mongodb sg-710ffa14

또한 일치하는 여러 구조체를 표시할 수도 있습니다.

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[*].[GroupName,GroupId]' \
  --instance-id i-6b272337 \
  --output text
mongodb sg-710ffa14
default sg-a0243bcc

관련 정보