Ho un output JSON da cui devo estrarre alcuni parametri in Linux.
Questo è l'output 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
}
]
}
Voglio scrivere un file che contenga intestazione come ID istanza, tag come nome, centro di costo, proprietario. e al di sotto di determinati valori dall'output JSON. L'output qui fornito è solo un esempio.
Come posso farlo usando sed
e awk
?
Risultato previsto :
Instance id Name cost centre Owner
i-1234576 RDS_Machine (us-east-1c) 1234 Jyoti
Risposta accettata:
La disponibilità di parser in quasi tutti i linguaggi di programmazione è uno dei vantaggi di JSON come formato di scambio dati.
Piuttosto che provare a implementare un parser JSON, è probabile che tu stia meglio utilizzando uno strumento creato per l'analisi JSON come jq o un linguaggio di script generico con una libreria JSON.
Ad esempio, utilizzando jq, puoi estrarre ImageID dal primo elemento dell'array Instances come segue:
jq '.Instances[0].ImageId' test.json
In alternativa, per ottenere le stesse informazioni utilizzando la libreria JSON di Ruby:
ruby -rjson -e 'j = JSON.parse(File.read("test.json")); puts j["Instances"][0]["ImageId"]'
Non risponderò a tutte le tue domande e commenti rivisti, ma si spera che quanto segue sia sufficiente per iniziare.
Supponiamo di avere uno script Ruby in grado di leggere a da STDIN e generare la seconda riga nell'output di esempio [0]. Quello script potrebbe assomigliare a:
#!/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}"
Come potresti usare un copione del genere per raggiungere il tuo intero obiettivo? Bene, supponiamo che tu abbia già quanto segue:
- un comando per elencare tutte le tue istanze
- un comando per ottenere il json sopra per qualsiasi istanza nell'elenco e inviarlo a STDOU
Un modo sarebbe usare la tua shell per combinare questi strumenti:
echo -e "Instance idtNametcost centretOwner"
for instance in $(list-instances); do
get-json-for-instance $instance | ./ugly-ruby-scriptrb
done
Ora, forse hai un singolo comando che ti dà un blob json per tutte le istanze con più elementi in quell'array "Istanze". Bene, in tal caso, dovrai solo modificare un po' lo script per scorrere l'array anziché utilizzare semplicemente il primo elemento.
Alla fine, il modo per risolvere questo problema è il modo per risolvere molti problemi in Unix. Scomponilo in problemi più facili. Trova o scrivi strumenti per risolvere il problema più semplice. Combina questi strumenti con la tua shell o altre funzionalità del sistema operativo.
[0] Nota che non ho idea di dove trovi il centro di costo, quindi l'ho appena inventato.