![Linux에서 쉘 스크립팅으로 JSON을 구문 분석하는 방법은 무엇입니까?](https://rvso.com/image/52096/Linux%EC%97%90%EC%84%9C%20%EC%89%98%20%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8C%85%EC%9C%BC%EB%A1%9C%20JSON%EC%9D%84%20%EA%B5%AC%EB%AC%B8%20%EB%B6%84%EC%84%9D%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
Linux에서 몇 가지 매개변수를 추출해야 하는 JSON 출력이 있습니다.
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
and 를 사용하여 어떻게 할 수 있나요 awk
?
예상 출력:
Instance id Name cost centre Owner
i-1234576 RDS_Machine (us-east-1c) 1234 Jyoti
답변1
거의 모든 프로그래밍 언어에서 파서를 사용할 수 있다는 점은 데이터 교환 형식인 JSON의 장점 중 하나입니다.
JSON 구문 분석기를 구현하는 것보다 다음과 같은 JSON 구문 분석용으로 구축된 도구를 사용하는 것이 더 나을 것입니다.jq또는 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을 제공하는 단일 명령이 있을 수 있습니다. 그렇다면 단순히 첫 번째 항목을 사용하는 대신 배열 전체를 반복하도록 스크립트를 약간 수정하면 됩니다.
결국 이 문제를 해결하는 방법은 유닉스의 많은 문제를 해결하는 방법이다. 더 쉬운 문제로 나누어 보세요. 더 쉬운 문제를 해결하기 위한 도구를 찾거나 작성하세요. 이러한 도구를 셸 또는 기타 운영 체제 기능과 결합하세요.
[0] 코스트 센터가 어디서 나오는지 모르기 때문에 그냥 만들어봤습니다.
답변2
다음 Python 스크립트를 사용하여 해당 데이터를 구문 분석할 수 있습니다. array1.json
와 같은 파일의 배열에서 JSON 데이터가 있다고 가정해 보겠습니다 array2.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를 추출하는 방법을 찾고 있었습니다. 이를 수행하려면 awk 구문 분석 가능한 문자열을 제공하는 aws 명령에 "--output=text" 인수를 전달할 수 있습니다. 이를 통해 다음과 같은 방법을 사용하여 간단히 인스턴스 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