JSON-Analyse auf der Shell

JSON-Analyse auf der Shell

Wie kann ich die JSON-Ausgabe in der Shell analysieren?

Beispielsweise bietet Amazon Web Services eine CLI zum Abrufen des Status Ihrer Instanzen:

$ aws ec2 describe-instances <my_instance_id>

Der Befehl gibt jedoch eine JSON-Zeichenfolge zurück. Die Ausgabe dieses Befehls sieht folgendermaßen aus:

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

Gibt es integrierte Shells, die zum Parsen der JSON-Ausgabe verwendet werden könnten?

Ich möchte beispielsweise FOOFolgendes in einer Shell-Variable erfassen output["Reservations"]["SecurityGroups"][0]{"Foo"}.

Falls es hilft, bin ich insbesondere an Lösungen interessiert, die von Zsh aus funktionieren könnten.

Antwort1

So wie ich es verstehe, suchen Sie nach dem Wert von "Foo". Das istWirklichDas geht ganz einfach mit dem Shell-Befehlszeilentool jq. Es ist so etwas wie seddie Implementierung einer eigenen Art von Parsersprache. In Ihrem Beispiel:

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

jqkann yesso einfach sein wie:

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

AUSGABE

"yes"

Sie können mithilfe der Notation durch einen Objekt-Hash oder eine Wörterbuchliste gehen .dot, und indizierte Arrays können einfacher indiziert werden, mit, wie Sie wahrscheinlich schon vermutet haben, numerischen, in eckige Klammern gesetzten Indizes. Im obigen Befehl verwende ich die leere Indexform, um anzugeben, dass ich alle iterierbaren Elemente dieser Ebene erweitert haben möchte. Das ist vielleicht auf diese Weise leichter zu verstehen:

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

... das alle Werte für die Elemente der zweiten Ebene im Hash aufschlüsselt und mir Folgendes liefert ...

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

Dies ist nur ein kleiner Ausschnitt der jqFähigkeiten von . Es ist ein immens leistungsfähiges Tool zum Serialisieren von Daten in der Shell, es kompiliert zu einer einzigen ausführbaren Binärdatei im klassischen Unix-Stil, es ist sehr wahrscheinlich über den Paketmanager für Ihre Distribution verfügbar und es ist sehr gut dokumentiert. Bitte besuchen Sie seinegit-Seiteund überzeugen Sie sich selbst.

Übrigens, eine andere Möglichkeit, geschichtete Daten anzugehen json- zumindest um eine Vorstellung davon zu bekommen, womit Sie arbeiten - könnte darin bestehen, den umgekehrten Weg zu gehen und die .dotNotation zu verwenden, um auszubrechenalleWerte beialleEbenen wie:

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"

Viel besser wäre es wahrscheinlich jedoch, einfach eine der vielen Erkennungs- oder Suchmethoden zu verwenden, die jqfür die verschiedenen Knotentypen angeboten werden.

Antwort2

Dies ist eine Antwort auf Ihr Ziel, aber nicht auf Ihre Frage. Das bedeutet, dass Sie Ihr Ziel erreichen können, ohne einen JSON-Parser zu verwenden.

Das AWS-CLI-Dienstprogramm kann nur ausgewählte Felder mit dem --queryArgument ausgeben. Dies ist dokumentiertHier.

Zum Beispiel:

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

Sie können bei Bedarf sogar mehrere Felder auswählen:

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

Und Sie können auch mehrere passende Strukturen anzeigen:

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

verwandte Informationen