json ファイルをループするにはどうすればいいですか?

json ファイルをループするにはどうすればいいですか?

以下の json ファイルがあり、name特定の値が含まれている場合にのみ hostId を取得したいと考えています。これを実現するには、シェル スクリプトを使用したいと思います。

{
  "items" : [ {
    "name" : "first-block-e70a2fe8fd0531ad1f87de49f03537a6",
    "type" : "STORE",
    "hostRef" : {
      "hostId" : "166219e3-be5c-46d0-b4c7-33543a29ce32"
    },
    "roleState" : "STARTED",
    "healthSummary" : "GOOD",

    },
  {
   "name" : "second-block-c21a1ae8dd2831cd1b87de49f98274e8",
    "type" : "STORE",
    "hostRef" : {
      "hostId" : "176429e3-be5c-46d0-b4c7-33543a29ad63"
    },
    "roleState" : "STARTED",
    "healthSummary" : "GOOD",
  }

  {
   "name" : "first-block-a85d2fe6fd0482ad1f54de49f45174a0",
    "type" : "STORE",
    "hostRef" : {
      "hostId" : "176429e3-ae1d-46d0-b4c7-66123a24fa82"
    },
    "roleState" : "STARTED",
    "healthSummary" : "GOOD",
  }

}

たとえば、名前に「first-block」が含まれている場合、hostIdは次のように取得されます。

166219e3-be5c-46d0-b4c7-33543a29ce32
176429e3-ae1d-46d0-b4c7-66123a24fa82

json ファイルを反復処理するにはどうすればいいですか? 特定の値を含む要素をフィルタリングしnameて取得するには、どのような正規表現を使用すればよいですかhostid?

答え1

jq を使うこともできます:

入力ファイル:

{
  "items" : [
    {
      "name" : "first-block-e70a2fe8fd0531ad1f87de49f03537a6",
      "type" : "STORE",
      "hostRef" : {
        "hostId" : "166219e3-be5c-46d0-b4c7-33543a29ce32"
      },
      "roleState" : "STARTED",
      "healthSummary" : "GOOD"

    },
    {
      "name" : "second-block-c21a1ae8dd2831cd1b87de49f98274e8",
      "type" : "STORE",
      "hostRef" : {
        "hostId" : "176429e3-be5c-46d0-b4c7-33543a29ad63"
      },
      "roleState" : "STARTED",
      "healthSummary" : "GOOD"
    },

    {
      "name" : "first-block-a85d2fe6fd0482ad1f54de49f45174a0",
      "type" : "STORE",
      "hostRef" : {
        "hostId" : "176429e3-ae1d-46d0-b4c7-66123a24fa82"
      },
      "roleState" : "STARTED",
      "healthSummary" : "GOOD"
    }
  ]
}

指示:

編集:@Runium の貢献により

$ jq '.items[] | select( .name | startswith("first-block-"))|.hostRef.hostId' < file.json 
"e70a2fe8fd0531ad1f87de49f03537a6"
"a85d2fe6fd0482ad1f54de49f45174a0"

答え2

Python を使用した非常にシンプルなサンプル:

#!/usr/bin/env python

import sys
import json

def print_first(data):
    for item in data["items"]:
        if item["name"].startswith("first"):
            print item["hostRef"]["hostId"]

def main(argv):
    for json_file in argv:
        with open(json_file) as data_file:
            data = json.load(data_file)
            print_first(data)

if __name__ == "__main__":
    main(sys.argv[1:])

サンプル データは次のように再フォーマットされます。

{
    "items" : [
        {
            "name" : "first-block-e70a2fe8fd0531ad1f87de49f03537a6",
            "type" : "STORE",
            "hostRef" : {
                "hostId" : "166219e3-be5c-46d0-b4c7-33543a29ce32"
            },
            "roleState" : "STARTED",
            "healthSummary" : "GOOD"

        },
        {
            "name" : "second-block-c21a1ae8dd2831cd1b87de49f98274e8",
            "type" : "STORE",
            "hostRef" : {
                "hostId" : "176429e3-be5c-46d0-b4c7-33543a29ad63"
            },
            "roleState" : "STARTED",
            "healthSummary" : "GOOD"
        },
        {
            "name" : "first-block-a85d2fe6fd0482ad1f54de49f45174a0",
            "type" : "STORE",
            "hostRef" : {
                "hostId" : "176429e3-ae1d-46d0-b4c7-66123a24fa82"
            },
            "roleState" : "STARTED",
            "healthSummary" : "GOOD"
        }
    ]
}

答え3

@Theophrastus が述べたように、まず JSON パーサーをインストールする必要がありますjq。その後は、必要な値をフィルタリングするだけです。

投稿した JSON ブロックは有効ではないことを述べておきます。「items」の開き括弧が閉じられておらず、2 番目のエントリにはitemsコンマ区切りが必要です。それにもかかわらず、有効なブロックがあり、関連すると思われる部分のみを切り取って貼り付けたと仮定します。各ブロックが実際に代表的である場合、追加する必要があるのは (bashシェルであると仮定して) 次の2 つだけです。

echo "${YOUR_JSON_BLOCK}"  |  jq '.items[].hostRef.hostId'

YOUR_JSON_BLOCK がデータを含む完全な有効な JSON 文字列であると仮定すると、指定された行だけが出力されます。

答え4

最近、私はそのようなJSONクエリを処理するためのより簡単なUnix/シェルの代替案(完全にFOSSで無料)を思いつきました - 見てみましょうjtcこのツールを使用すると、相対ウォーク (つまり、1 つを見つけて別のウォークにオフセットする) を処理できます。

元の json が修正されていると仮定すると (いくつかの問題があります)、cli は次のようになります。

bash $ cat file.json | jtc -w'[name]:<^first-block>R: [-1] [hostRef] [hostId]'
"166219e3-be5c-46d0-b4c7-33543a29ce32"
"176429e3-ae1d-46d0-b4c7-66123a24fa82"
bash $ 

関連情報