Linux에서 쉘 스크립트를 사용하여 JSON을 구문 분석하는 방법은 무엇입니까?

Linux에서 쉘 스크립트를 사용하여 JSON을 구문 분석하는 방법은 무엇입니까?

JSON 출력이 있고 Linux에서 일부 매개변수를 추출해야 합니다.

JSON 출력은 다음과 같습니다.

{
        "OwnerId": "121456789127",
        "ReservationId": "r-48465168",
        "Groups": [],
        "Instances": [
            {
                "Monitoring": {
                    "State": "disabled"
                },
                "PublicDnsName": null,
                "RootDeviceType": "ebs",
                "State": {
                    "Code": 16,
                    "Name": "running"
                },
                "EbsOptimized": false,
                "LaunchTime": "2014-03-19T09:16:56.000Z",
                "PrivateIpAddress": "10.250.171.248",
                "ProductCodes": [
                    {
                        "ProductCodeId": "aacglxeowvn5hy8sznltowyqe",
                        "ProductCodeType": "marketplace"
                    }
                ],
                "VpcId": "vpc-86bab0e4",
                "StateTransitionReason": null,
                "InstanceId": "i-1234576",
                "ImageId": "ami-b7f6c5de",
                "PrivateDnsName": "ip-10-120-134-248.ec2.internal",
                "KeyName": "Test_Virginia",
                "SecurityGroups": [
                    {
                        "GroupName": "Test",
                        "GroupId": "sg-12345b"
                    }
                ],
                "ClientToken": "VYeFw1395220615808",
                "SubnetId": "subnet-12345314",
                "InstanceType": "t1.micro",
                "NetworkInterfaces": [
                    {
                        "Status": "in-use",
                        "SourceDestCheck": true,
                        "VpcId": "vpc-123456e4",
                        "Description": "Primary network interface",
                        "NetworkInterfaceId": "eni-3619f31d",
                        "PrivateIpAddresses": [
                            {
                                "Primary": true,
                                "PrivateIpAddress": "10.120.134.248"
                            }
                        ],
                        "Attachment": {
                            "Status": "attached",
                            "DeviceIndex": 0,
                            "DeleteOnTermination": true,
                            "AttachmentId": "eni-attach-9210dee8",
                            "AttachTime": "2014-03-19T09:16:56.000Z"
                        },
                        "Groups": [
                            {
                                "GroupName": "Test",
                                "GroupId": "sg-123456cb"
                            }
                        ],
                        "SubnetId": "subnet-31236514",
                        "OwnerId": "109030037527",
                        "PrivateIpAddress": "10.120.134.248"
                    }
                ],
                "SourceDestCheck": true,
                "Placement": {
                    "Tenancy": "default",
                    "GroupName": null,
                    "AvailabilityZone": "us-east-1c"
                },
                "Hypervisor": "xen",
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sda",
                        "Ebs": {
                            "Status": "attached",
                            "DeleteOnTermination": false,
                            "VolumeId": "vol-37ff097b",
                            "AttachTime": "2014-03-19T09:17:00.000Z"
                        }
                    }
                ],
                "Architecture": "x86_64",
                "KernelId": "aki-88aa75e1",
                "RootDeviceName": "/dev/sda1",
                "VirtualizationType": "paravirtual",
                "Tags": [
                    {
                        "Value": "Server for testing RDS feature in us-east-1c AZ",
                        "Key": "Description"
                    },
                    {
                        "Value": "RDS_Machine (us-east-1c)",
                        "Key": "Name"
                    },
                    {
                        "Value": "1234",
                        "Key": "cost.centre",
                      },
                    {
                        "Value": "Jyoti Bhanot",
                        "Key": "Owner",
                      }
                ],
                "AmiLaunchIndex": 0
            }
        ]
    }

인스턴스 ID와 같은 제목, 이름, 비용 센터, 소유자와 같은 태그가 있는 파일을 작성하고 싶습니다. JSON 출력 아래의 일부 값. 여기에 제공된 출력은 단지 예일 뿐입니다.

sed및 을 사용하여 이 작업을 어떻게 수행할 수 있습니까 awk?

예상 출력:

 Instance id         Name                           cost centre             Owner
    i-1234576          RDS_Machine (us-east-1c)        1234                   Jyoti

답변1

거의 모든 프로그래밍 언어는 데이터 교환 형식으로서 JSON의 장점 중 하나인 파서를 제공합니다.

JSON 구문 분석을 위해 구축된 도구를 사용하는 것이 더 나을 것입니다.또는 JSON 라이브러리가 있는 일반 스크립팅 언어입니다.

예를 들어 jq를 사용하면 다음과 같이 Instances 배열의 첫 번째 항목에서 ImageID를 추출할 수 있습니다.

jq '.Instances[0].ImageId' test.json

또는 Ruby의 JSON 라이브러리를 사용하여 동일한 정보를 얻으려면 다음을 수행하세요.

ruby -rjson -e 'j = JSON.parse(File.read("test.json")); puts j["Instances"][0]["ImageId"]'

귀하가 수정한 모든 질문과 의견에 답변하지는 않겠지만, 다음 내용이 시작하는 데 충분할 것입니다.

STDIN에서 a를 읽고 예제 출력 [0]의 두 번째 줄을 인쇄하는 Ruby 스크립트가 있다고 가정합니다. 스크립트는 다음과 같습니다.

#!/usr/bin/env ruby
require 'json'

data = JSON.parse(ARGF.read)
instance_id = data["Instances"][0]["InstanceId"]
name = data["Instances"][0]["Tags"].find {|t| t["Key"] == "Name" }["Value"]
owner = data["Instances"][0]["Tags"].find {|t| t["Key"] == "Owner" }["Value"]
cost_center = data["Instances"][0]["SubnetId"].split("-")[1][0..3]
puts "#{instance_id}\t#{name}\t#{cost_center}\t#{owner}"

전체 목표를 달성하기 위해 이와 같은 스크립트를 어떻게 사용합니까? 음, 이미 다음이 있다고 가정해 보겠습니다.

  • 모든 인스턴스를 나열하는 명령
  • 목록의 모든 인스턴스에 대해 위 json을 가져와 STDOU로 출력하는 명령

한 가지 방법은 셸을 사용하여 다음 도구를 결합하는 것입니다.

echo -e "Instance id\tName\tcost centre\tOwner"
for instance in $(list-instances); do
    get-json-for-instance $instance | ./ugly-ruby-scriptrb
done

이제 "인스턴스" 배열에 더 많은 항목이 포함된 모든 인스턴스에 대한 json blob을 제공하는 명령이 있을 수 있습니다. 그렇다면 단순히 첫 번째 항목을 사용하는 대신 배열을 반복하도록 스크립트를 약간 수정하면 됩니다.

이 문제에 대한 궁극적인 해결책은 Unix의 많은 문제에 대한 해결책입니다. 더 간단한 질문으로 나누어 보세요. 더 간단한 문제를 해결하기 위한 도구를 찾거나 작성하세요. 이러한 도구를 셸 또는 기타 운영 체제 기능과 결합하세요.

[0] 비용 센터를 어디서 얻었는지 모르기 때문에 방금 만들어봤습니다.

답변2

다음 Python 스크립트를 사용하여 이 데이터를 구문 분석할 수 있습니다. .array1.jsonarray2.json

import json
import sys
from pprint import pprint

jdata = open(sys.argv[1])

data = json.load(jdata)

print "InstanceId", " - ", "Name", " - ", "Owner"
print data["Instances"][0]["InstanceId"], " - " ,data["Instances"][0]["Tags"][1]["Value"], " - " ,data["Instances"][0]["Tags"][2]["Value"] 

jdata.close()

그런 다음 다음을 실행하십시오.

$ for x in `ls *.json`; do python parse.py $x; done
InstanceId  -  Name  -  Owner
i-1234576  -  RDS_Machine (us-east-1c)  -  Jyoti Bhanot

귀하의 데이터에 비용이 표시되지 않기 때문에 포함하지 않았습니다.

댓글의 논의를 바탕으로,parse.py 스크립트를 업데이트했습니다.

import json
import sys
from pprint import pprint

jdata = sys.stdin.read()

data = json.loads(jdata)

print "InstanceId", " - ", "Name", " - ", "Owner"
print data["Instances"][0]["InstanceId"], " - " ,data["Instances"][0]["Tags"][1]["Value"], " - " ,data["Instances"][0]["Tags"][2]["Value"] 

다음 명령을 실행해 볼 수 있습니다.

#ec2-describe-instance <instance> | python parse.py

답변3

다른 사람들은 귀하의 질문에 대해 json을 구문 분석하는 좋은 방법을 보여주는 일반적인 답변을 제공했지만, 저는 귀하와 마찬가지로 다른 패키지에 의존하지 않고 awk 또는 sed와 같은 핵심 도구를 사용하여 aws 인스턴스 ID를 추출하는 방법을 찾고 있습니다. 이를 달성하려면 "--output=text" 매개변수를 aws 명령에 전달하면 awk 구문 분석 가능한 문자열이 제공됩니다. 이렇게 하면 다음과 같은 방법을 사용하여 간단히 인스턴스 ID를 얻을 수 있습니다.

aws ec2 run-instances --output text  | awk -F"\t" '$1=="INSTANCES" {print $8}'

답변4

위에 제공된 AWS 사용 사례로 제한되는 경우 CLI API 호출에 --query 및 --output 플래그를 사용해야 합니다.

http://docs.aws.amazon.com/cli/latest/userguide/controlling-output.html

관련 정보