Как проанализировать JSON с помощью скриптов оболочки в Linux?

Как проанализировать JSON с помощью скриптов оболочки в Linux?

У меня есть вывод 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
            }
        ]
    }

Я хочу написать файл, который содержит заголовок типа идентификатора экземпляра, тег типа имени, центра затрат, владельца. и ниже определенные значения из вывода JSON. Приведенный здесь вывод — это всего лишь пример.

Как это сделать с помощью sedи awk?

Ожидаемый результат:

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

решение1

Наличие парсеров практически на каждом языке программирования является одним из преимуществ JSON как формата обмена данными.

Вместо того, чтобы пытаться реализовать парсер JSON, вам, вероятно, лучше использовать инструмент, созданный для парсинга JSON, такой какjqили язык сценариев общего назначения, имеющий библиотеку JSON.

Например, используя jq, вы можете извлечь ImageID из первого элемента массива Instances следующим образом:

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

Альтернативный способ получить ту же информацию с помощью библиотеки JSON Ruby:

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

Я не буду отвечать на все ваши пересмотренные вопросы и комментарии, но надеюсь, что нижеизложенного будет достаточно, чтобы вы могли начать.

Предположим, что у вас есть скрипт Ruby, который может считывать a из STDIN и выводить вторую строку в вашем примере output[0]. Этот скрипт может выглядеть примерно так:

#!/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 для всех экземпляров с большим количеством элементов в этом массиве "Instances". Ну, если это так, вам просто нужно немного изменить скрипт, чтобы выполнить итерацию по массиву, а не просто использовать первый элемент.

В конце концов, способ решения этой проблемы — это способ решения многих проблем в Unix. Разбейте ее на более простые проблемы. Найдите или напишите инструменты для решения более простой проблемы. Объедините эти инструменты с вашей оболочкой или другими функциями операционной системы.

[0] Обратите внимание, что я понятия не имею, откуда вы взяли термин «центр затрат», поэтому я его просто выдумал.

решение2

Вы можете использовать следующий скрипт python для разбора этих данных. Предположим, что у вас есть данные JSON из массивов в файлах типа array1.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, однако я, как и вы, искал способ извлечь идентификатор экземпляра aws с помощью основного инструмента, такого как awk или sed, без зависимости от других пакетов. Чтобы сделать это, вы можете передать аргумент "--output=text" вашей команде aws, которая даст вам строку, пригодную для разбора awk. С этим вы можете просто получить идентификатор экземпляра, используя что-то вроде следующего...

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

решение4

Если это ограничивается вариантом использования AWS, представленным выше, вам следует использовать флаги --query и --output для вызова API CLI.

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

Связанный контент