シェルでのJSON解析


11

シェルでJSON出力を解析するにはどうすればよいですか?

たとえば、Amazon Webサービスには、インスタンスのステータスを取得するためのCLIが用意されています。

$ aws ec2 describe-instances <my_instance_id>

しかし、コマンドはJSON文字列を返します。このコマンドの出力は次のようになります。

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

JSON出力の解析に使用できるシェルの組み込みはありますか?

たとえばFOO、次のシェル変数にキャプチャしたいとしますoutput["Reservations"]["SecurityGroups"][0]{"Foo"}

それが役立つ場合、私は特にZshで動作するソリューションに興味があります。


2
通常は、jshonなどのツールを使用します。
jasonwryan 2014年

1
--output textような外部ツールを使用せずにシェルで解析したい場合に使用しますjshon
ヨルダン2014年

1
@jasonwryan- jshon初めて聞いたばかりなので、私はあなたのリンクをたどりました。それを読んで、私が偶然にjq最初に聞いてインストールしたことを非常に嬉しく思いました。まだお聞きになっていない方もいらっしゃると思います。すべてのコマンドラインスイッチを気にする必要がなく、独自の正規表現を実行できます。必要に応じて、関数や変数を宣言することもできます。興味があればこちらで答えをご覧ください。
mikeserv 2014年

回答:


10

私が理解しているように、あなたは「フー」の価値を探しています。これは、実際には、シェルのコマンドラインツールで行うのは簡単jq。それはsed、独自の種類のパーサー言語を実装しているようなものです。あなたの例を考えると:

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

jq簡単に取得できますyes

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

出力

"yes"

.dot表記法を使用してオブジェクトハッシュまたはディクショナリリストをウォークスルーでき、インデックス付き配列は、おそらく推測されたように、角括弧で囲まれたインデックスを使用して、より簡単にインデックスを付けることができます。上記のコマンドでは、空のインデックスフォームを使用して、そのレベルのすべての反復可能な項目を展開することを示しています。次のようにすると、理解しやすくなります。

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

...ハッシュの2番目のレベルの項目のすべての値を分解して、私を取得します...

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

これは、jqの機能に関して表面をかろうじて引っ掻きます。これは、シェルでデータをシリアル化するための非常に強力なツールであり、古典的なUnixスタイルの単一の実行可能バイナリにコンパイルされます。ディストリビューションのパッケージマネージャーを介して利用できる可能性が高く、十分に文書化されています。そのgitページにアクセスして、自分ので確かめてください。

ところで、階層化データに取り組むための別の方法json-少なくとも作業しているものを理解するために-は別の方法で、.dot表記法を使用して次のようなすべてのレベルのすべての値を分解することです:

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"

しかし、おそらく、はるかに優れjqているのは、さまざまなタイプのノードに提供される多くのディスカバリーまたは検索メソッドの1つを使用することです。


10

これはあなたの目的に対する答えですが、あなたの質問ではありません。つまり、JSONパーサーを使用せずに目標を達成できるということです。

AWS cli utilには、--query引数を使用して選択フィールドのみを出力する機能があります。これはここに文書化されています

例えば:

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

必要に応じて、複数のフィールドを選択することもできます。

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

また、複数の一致する構造体を表示することもできます。

$ 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
ありがとう!それはとても助かります。私は、質問への回答をコミュニティに提供するために、@ mikeservを主に受け入れていますが、あなたの回答は、私が使用するものです
Amelio Vazquez-Reina

これはとても役に立ちます!どうもありがとうございました!!
MD Sayem Ahmed 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.