Análisis JSON en el shell

Análisis JSON en el shell

¿Cómo puedo analizar la salida JSON en el shell?

Por ejemplo, Amazon Web Services proporciona una CLI para recuperar el estado de sus instancias:

$ aws ec2 describe-instances <my_instance_id>

Pero el comando devuelve una cadena JSON. La salida de ese comando se ve así:

$ aws ec2 describe-instances x12345
{
    "Reservations" :
     {  
            "OwnerId": "1345345"
            "Groups": [], 
            "SecurityGroups": [
               {
                  "Foo" : "yes"
                  "Bar" : "no
               }
             ]
     }
}

¿Existen shells integrados que podrían usarse para analizar la salida JSON?

Por ejemplo, me gustaría capturar en una variable de shell FOOlo siguiente output["Reservations"]["SecurityGroups"][0]{"Foo"}.

En caso de que ayude, estoy específicamente interesado en soluciones que podrían funcionar desde Zsh.

Respuesta1

Según tengo entendido, estás buscando el valor de "Foo". Esto esen realidadfácil de hacer con la herramienta de línea de comandos del shell jq. Es algo así sedcomo que implementa su propio tipo de lenguaje analizador. Dado su ejemplo:

json='
{
    "Reservations" :
     {  
            "OwnerId" : "1345345",
            "Groups" :  [],
            "SecurityGroups" : [
               {
                  "Foo" : "yes",
                  "Bar" : "no"
               }
             ]
     }
}'

jqpuede ser yestan simple como:

printf %s "$json" |
jq '.[].SecurityGroups[0].Foo?'                                                

PRODUCCIÓN

"yes"

Puede recorrer un hash de objetos o una lista de diccionario usando la .dotnotación, y las matrices indexadas se pueden indexar de manera más simple, con, como probablemente habrá adivinado, índices numéricos entre corchetes. En el comando anterior utilizo el formulario de índice vacío para indicar que quiero expandir todos los elementos iterables de ese nivel. Quizás sea más fácil de entender de esta manera:

printf %s "$json" | jq '.[][]'

... que desglosa todos los valores de los elementos de segundo nivel en el hash y me atrapa...

"1345345"
[]
[
  {
    "Foo": "yes",
    "Bar": "no"
  }
]

Esto apenas roza la superficie con respecto a jqlas capacidades de. Es una herramienta inmensamente poderosa para serializar datos en el shell, se compila en un único binario ejecutable en el estilo clásico de Unix, es muy probable que esté disponible a través del administrador de paquetes para su distribución y está muy bien documentado. Por favor visite sugit-páginay compruébalo por ti mismo.

Por cierto, otra manera de abordar los datos en capas json(al menos para tener una idea de con qué estás trabajando) podría ser ir al otro lado y usar la .dotnotación para separarlos.todovalores entodoniveles como:

printf %s "$json" | jq '..'

{
  "Reservations": {
    "OwnerId": "1345345",
    "Groups": [],
    "SecurityGroups": [
      {
        "Foo": "yes",
        "Bar": "no"
      }
    ]
  }
}
{
  "OwnerId": "1345345",
  "Groups": [],
  "SecurityGroups": [
    {
      "Foo": "yes",
      "Bar": "no"
    }
  ]
}
"1345345"
[]
[
  {
    "Foo": "yes",
    "Bar": "no"
  }
]
{
  "Foo": "yes",
  "Bar": "no"
}
"yes"
"no"

Pero probablemente sería mucho mejor utilizar uno de los muchos métodos de descubrimiento o búsqueda que jqse ofrecen para los distintos tipos de nodos.

Respuesta2

Esta es una respuesta a su objetivo, pero no a su pregunta. Lo que significa que puede lograr su objetivo sin utilizar un analizador JSON.

La utilidad AWS cli tiene la capacidad de generar solo campos seleccionados utilizando el --queryargumento. esto esta documentadoaquí.

Por ejemplo:

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[0].GroupName' \
  --instance-id i-6b272337 \
  --output text
mongodb

Incluso puedes seleccionar varios campos si lo deseas:

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[0].[GroupName,GroupId]' \
  --instance-id i-6b272337 \
  --output text
mongodb sg-710ffa14

Y también puedes mostrar múltiples estructuras coincidentes:

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[*].[GroupName,GroupId]' \
  --instance-id i-6b272337 \
  --output text
mongodb sg-710ffa14
default sg-a0243bcc

información relacionada