Tengo una salida JSON de la que necesito extraer algunos parámetros en Linux.
Esta es la salida 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
}
]
}
Quiero escribir un archivo que contenga encabezado como ID de instancia, etiqueta como nombre, centro de costos, propietario. y debajo de eso, ciertos valores de la salida JSON. El resultado aquí dado es solo un ejemplo.
¿Cómo puedo hacer eso usando sed
? y awk
?
Resultado esperado:
Instance id Name cost centre Owner
i-1234576 RDS_Machine (us-east-1c) 1234 Jyoti
Respuesta aceptada:
La disponibilidad de analizadores en casi todos los lenguajes de programación es una de las ventajas de JSON como formato de intercambio de datos.
En lugar de intentar implementar un analizador JSON, probablemente sea mejor que utilice una herramienta creada para el análisis JSON, como jq, o un lenguaje de secuencias de comandos de propósito general que tenga una biblioteca JSON.
Por ejemplo, al usar jq, puede extraer el ID de imagen del primer elemento de la matriz Instancias de la siguiente manera:
jq '.Instances[0].ImageId' test.json
Alternativamente, para obtener la misma información utilizando la biblioteca JSON de Ruby:
ruby -rjson -e 'j = JSON.parse(File.read("test.json")); puts j["Instances"][0]["ImageId"]'
No responderé a todas sus preguntas y comentarios revisados, pero espero que lo siguiente sea suficiente para comenzar.
Suponga que tiene un script de Ruby que puede leer un STDIN y generar la segunda línea en su salida de ejemplo [0]. Esa secuencia de comandos podría parecerse 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}"
¿Cómo podría usar un guión así para lograr todo su objetivo? Bueno, supongamos que ya tiene lo siguiente:
- un comando para enumerar todas sus instancias
- un comando para obtener el json anterior para cualquier instancia en su lista y enviarlo a STDOU
Una forma sería usar su caparazón para combinar estas herramientas:
echo -e "Instance idtNametcost centretOwner"
for instance in $(list-instances); do
get-json-for-instance $instance | ./ugly-ruby-scriptrb
done
Ahora, tal vez tenga un solo comando que le proporcione un json blob para todas las instancias con más elementos en esa matriz de "Instancias". Bueno, si ese es el caso, solo necesitará modificar un poco la secuencia de comandos para iterar a través de la matriz en lugar de simplemente usar el primer elemento.
Al final, la forma de resolver este problema es la forma de resolver muchos problemas en Unix. Divídelo en problemas más fáciles. Encuentre o escriba herramientas para resolver el problema más fácil. Combine esas herramientas con su shell u otras características del sistema operativo.
[0] Tenga en cuenta que no tengo idea de dónde obtiene el centro de costos, así que lo inventé.