Ich habe eine JSON-Ausgabe, aus der ich einige Parameter in Linux extrahieren muss.
Dies ist die JSON-Ausgabe:
{
"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
}
]
}
Ich möchte eine Datei schreiben, die Überschriften wie Instanz-ID, Tags wie Name, Kostenstelle, Eigentümer enthält. und darunter bestimmte Werte aus der JSON-Ausgabe. Die hier angegebene Ausgabe ist nur ein Beispiel.
Wie kann ich das mit sed
machen? und awk
?
Erwartete Ausgabe:
Instance id Name cost centre Owner
i-1234576 RDS_Machine (us-east-1c) 1234 Jyoti
Akzeptierte Antwort:
Die Verfügbarkeit von Parsern in fast jeder Programmiersprache ist einer der Vorteile von JSON als Datenaustauschformat.
Anstatt zu versuchen, einen JSON-Parser zu implementieren, ist es wahrscheinlich besser, entweder ein für JSON-Parsing entwickeltes Tool wie jq oder eine Allzweck-Skriptsprache mit einer JSON-Bibliothek zu verwenden.
Beispielsweise könnten Sie mit jq die ImageID wie folgt aus dem ersten Element des Instances-Arrays ziehen:
jq '.Instances[0].ImageId' test.json
Alternativ können Sie dieselben Informationen auch mit der JSON-Bibliothek von Ruby abrufen:
ruby -rjson -e 'j = JSON.parse(File.read("test.json")); puts j["Instances"][0]["ImageId"]'
Ich werde nicht alle Ihre überarbeiteten Fragen und Kommentare beantworten, aber das Folgende reicht hoffentlich aus, um Ihnen den Einstieg zu erleichtern.
Angenommen, Sie hätten ein Ruby-Skript, das a aus STDIN lesen und die zweite Zeile in Ihrem Beispiel output[0] ausgeben könnte. Dieses Skript könnte etwa so aussehen:
#!/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}"
Wie könnten Sie ein solches Skript verwenden, um Ihr ganzes Ziel zu erreichen? Angenommen, Sie hatten bereits Folgendes:
- ein Befehl zum Auflisten aller Ihrer Instanzen
- Ein Befehl, um den JSON oben für jede Instanz auf Ihrer Liste abzurufen und an STDOU auszugeben
Eine Möglichkeit wäre, Ihre Shell zu verwenden, um diese Tools zu kombinieren:
echo -e "Instance idtNametcost centretOwner"
for instance in $(list-instances); do
get-json-for-instance $instance | ./ugly-ruby-scriptrb
done
Nun, vielleicht haben Sie einen einzigen Befehl, der Ihnen einen JSON-Blob für alle Instanzen mit mehr Elementen in diesem „Instances“-Array gibt. Nun, wenn das der Fall ist, müssen Sie das Skript nur ein wenig ändern, um das Array zu durchlaufen, anstatt einfach das erste Element zu verwenden.
Letztendlich ist der Weg zur Lösung dieses Problems der Weg zur Lösung vieler Probleme in Unix. Unterteilen Sie es in einfachere Probleme. Finden oder schreiben Sie Werkzeuge, um das einfachere Problem zu lösen. Kombinieren Sie diese Tools mit Ihrer Shell oder anderen Betriebssystemfunktionen.
[0] Beachten Sie, dass ich keine Ahnung habe, woher Sie die Kostenstelle bekommen, also habe ich es einfach erfunden.