Analisi JSON sulla shell


11

Come posso analizzare l'output JSON sulla shell?

Ad esempio, Amazon Web Services fornisce una CLI per recuperare lo stato delle tue istanze:

$ aws ec2 describe-instances <my_instance_id>

Ma il comando restituisce una stringa JSON. L'output di quel comando è simile al seguente:

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

Esistono built-in di shell che potrebbero essere utilizzati per analizzare l'output JSON?

Ad esempio, vorrei acquisire in una variabile di shell FOO, la seguente output["Reservations"]["SecurityGroups"][0]{"Foo"}.

Nel caso in cui aiuti, sono specificamente interessato a soluzioni che potrebbero funzionare da Zsh.


2
In genere useresti uno strumento, come jshon .
Jasonwryan,

1
Utilizzare --output textse si desidera analizzare nella shell senza utilizzare strumenti esterni come jshon.
Giordania,

1
@jasonwryan - Avendo sentito parlare solo ora jshonper la prima volta, ho seguito il tuo link. Dopo averlo letto, posso solo dire che sono rimasto molto contento di averlo sentito e installato jqper caso. Penso che ti piacerebbe sentirne parlare anche se non l'hai già fatto - non si preoccupa di tutte quelle opzioni della riga di comando e può fare le sue regex - ti permette anche di dichiarare funzioni e variabili se lo desideri. Vedi la risposta qui a riguardo se sei interessato.
Mikeserv,

Risposte:


10

A quanto ho capito stai cercando il valore di "Foo". Questo è davvero facile da fare con lo strumento da riga di comando della shell jq. È qualcosa di simile sednel fatto che implementa il proprio tipo di linguaggio parser. Dato il tuo esempio:

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

jqpuò ottenere yessemplicemente come:

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

PRODUZIONE

"yes"

È possibile scorrere un hash di un oggetto o un elenco di dizionari usando la .dotnotazione e gli array indicizzati possono essere indicizzati in modo più semplice, con, come probabilmente avete indovinato, indici numerici, a parentesi quadre. Nel comando sopra uso il modulo indice vuoto per indicare che desidero espandere tutti gli elementi iterabili di quel livello. Potrebbe essere più facile da capire in questo modo:

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

... che suddivide tutti i valori per gli oggetti di secondo livello nell'hash e mi ottiene ...

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

Questo a malapena graffia la superficie per quanto riguarda jqle capacità. È uno strumento estremamente potente per serializzare i dati nella shell, si compila in un singolo binario eseguibile nel classico stile Unix, è molto probabilmente disponibile tramite il gestore dei pacchetti per la tua distribuzione ed è molto ben documentato. Si prega di visitare la sua gitpagina e vedere di persona.

A proposito, un altro modo per affrontare i dati a più livelli json- almeno per avere un'idea di ciò con cui stai lavorando - potrebbe essere quello di andare dall'altra parte e usare la .dotnotazione per dividere tutti i valori a tutti i livelli come:

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"

Ma molto meglio, probabilmente, sarebbe solo usare uno dei molti metodi di scoperta o ricerca che jqoffre per i vari tipi di nodi.


10

Questa è una risposta al tuo obiettivo, ma non alla tua domanda. Ciò significa che puoi raggiungere il tuo obiettivo senza utilizzare un parser JSON.

AWS cli util ha la capacità di produrre solo campi selezionati usando l' --queryargomento. Questo è documentato qui .

Per esempio:

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

Puoi anche selezionare più campi se desideri:

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

E puoi anche mostrare più strutture corrispondenti:

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

1
Grazie! È molto utile. Accetto @mikeserv principalmente per servire la comunità con la risposta alla domanda, ma la tua risposta è quella che userò
Amelio Vazquez-Reina

Questo è molto utile! Grazie mille!!
MD Sayem Ahmed,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.