Json फ़ाइल के माध्यम से लूप कैसे करें?


6

मेरे पास एक निचे json फाइल है और मैं hostId प्राप्त करना चाहता हूं, केवल तभी जब nameकुछ विशिष्ट मूल्य हो। मैं इसे प्राप्त करने के लिए शेल स्क्रिप्ट का उपयोग करना चाहता हूं।

{
  "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",
  }

}

उदाहरण के लिए: यदि नाम में 'पहले-ब्लॉक' के साथ कुछ है तो मुझे hosdId के रूप में मिलना चाहिए

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

मैं json फ़ाइल के माध्यम से पुनरावृति कैसे कर सकता हूं? उस तत्व को फ़िल्टर करने के लिए मुझे किस regex का उपयोग करना चाहिए जिसमें कुछ विशिष्ट मूल्य हैं nameऔर प्राप्त करें hostid?


2
आप jshon जैसे json parser चाहते हैं ।
jasonwryan

शेल स्क्रिप्ट का समर्थन करने वाली कोई भी चीज ठीक होगी।
एलेक्स राज कालीमूर्ति

3
शायद 4 से 7 सड़कें आपको jq तक ले जाएंगी, लेकिन यहाँ पर और कुछ अन्य लोगों के लिए एक अच्छा अवलोकन है: stackoverflow.com/questions/27127091/parse-json-in-shell
थियोफ्रेस्टस

जवाबों:


2

अजगर का उपयोग कर एक बहुत ही सरल नमूना:

#!/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"
        }
    ]
}

4

आप 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"
    }
  ]
}

आदेश:

संपादित करें: @ रनियम के योगदान के साथ

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

1
विश्वास है कि में होना चाहिए jq '.items[] | select( .name | startswith("first-block-"))|.hostRef.hostId': वह चाहता है hostId, नहीं हैश का भागname
20:27 पर Runium

@adonis, @Runium, जब मैं यह कोशिश करता हूं तो मुझे नीचे की त्रुटि मिलती है./test.sh: line 1: jq: command not found
एलेक्स राज कालीमूर्ति

आपको स्थापित करना चाहिए jq। ऐसा करने का तरीका आपके डिस्ट्रो पर निर्भर करता है।
adonis

1

jqपहले ही कुछ बार उल्लेख किया गया है, इसलिए मैं उल्लेख करूंगा jsonpipe। यह धर्मान्तरित jsonएक लाइन उन्मुख तरह प्रसंस्करण के लिए उपयुक्त प्रारूप आदेश उपकरणों के साथ करने के लिए डेटा grep, sed, awk, perl, आदि यह के साथ काम करने के लिए दोनों एक कमांड लाइन उपकरण है jsonएक खोल में, और एक अजगर पुस्तकालय।

उदाहरण के लिए, यदि आपका नमूना json डेटा नामक फ़ाइल में सहेजा जाता है alex.json, और फिर संपादित किया जाता है ताकि यह वास्तव में मान्य json हो:

$ jsonpipe < alex.json 
/   {}
/items  []
/items/0    {}
/items/0/name   "first-block-e70a2fe8fd0531ad1f87de49f03537a6"
/items/0/type   "STORE"
/items/0/hostRef    {}
/items/0/hostRef/hostId "166219e3-be5c-46d0-b4c7-33543a29ce32"
/items/0/roleState  "STARTED"
/items/0/healthSummary  "GOOD"
/items/1    {}
/items/1/name   "second-block-c21a1ae8dd2831cd1b87de49f98274e8"
/items/1/type   "STORE"
/items/1/hostRef    {}
/items/1/hostRef/hostId "176429e3-be5c-46d0-b4c7-33543a29ad63"
/items/1/roleState  "STARTED"
/items/1/healthSummary  "GOOD"
/items/2    {}
/items/2/name   "first-block-a85d2fe6fd0482ad1f54de49f45174a0"
/items/2/type   "STORE"
/items/2/hostRef    {}
/items/2/hostRef/hostId "176429e3-ae1d-46d0-b4c7-66123a24fa82"
/items/2/roleState  "STARTED"
/items/2/healthSummary  "GOOD"

फिर आप इसे कुछ भी निकालने के लिए awk में पाइप कर सकते हैं, जो कि पैटर्न / प्रथम-ब्लॉक / से शुरू होने वाले / hostId / के साथ समाप्त होने वाली श्रेणी के दूसरे क्षेत्र में hostId जैसा दिखता है।

$ jsonpipe < alex.json  | 
    awk '/first-block/,/hostId/ {
             if ($2 ~ /\"[a-f0-9]{8}-/) {
                 gsub(/\"/,"",$2);
                 print $2
             }
         }'
166219e3-be5c-46d0-b4c7-33543a29ce32
176429e3-ae1d-46d0-b4c7-66123a24fa82

BTW, आप jsonpipe"पैराग्राफ" प्रारूप में आउटपुट प्राप्त कर सकते हैं , प्रत्येक "आइटम" के साथ एक अलग पैराग्राफ में इसे पाइप करके sed। इस मामले में, प्रत्येक आइटम रिकॉर्ड से पहले एक नई पंक्ति जोड़ें।

$ jsonpipe < alex.json | 
    sed -e 's/\/items\/[[:digit:]]\+[[:blank:]]\+/\n&/'
/   {}
/items  []

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

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

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

अनुच्छेद से पृथक डेटा एक बहुत ही आम स्वरूप है, और इस तरह आम उपकरणों awkऔर sedऔर perl1 विशेषताएं है कि यह आसान पैराग्राफ के साथ कार्य करने की है। इसके अलावा, इस तरह के काम के कई उदाहरण आसानी से इस और अन्य एसई साइटों पर पाए जाते हैं, साथ ही साथ Google भी।

अंत में, इस पंक्ति-उन्मुख फ्लैट प्रारूप को वापस जसन में बदलने के लिए jsonpipeएक jsonunpipeसमकक्ष है।

उदाहरण के लिए, यदि आप संरचना को समतल करना चाहते हैं, ताकि hostId के बजाय hostId एक आइटम की एक संपत्ति हो:

$ jsonpipe < alex.json  | 
      sed -e '/hostRef[[:blank:]]/d;s/hostRef\///' |
      jsonunpipe
{"items": [{"name": "first-block-e70a2fe8fd0531ad1f87de49f03537a6", "type": "STORE", "hostId": "166219e3-be5c-46d0-b4c7-33543a29ce32", "roleState": "STARTED", "healthSummary": "GOOD"}, {"name": "second-block-c21a1ae8dd2831cd1b87de49f98274e8", "type": "STORE", "hostId": "176429e3-be5c-46d0-b4c7-33543a29ad63", "roleState": "STARTED", "healthSummary": "GOOD"}, {"name": "first-block-a85d2fe6fd0482ad1f54de49f45174a0", "type": "STORE", "hostId": "176429e3-ae1d-46d0-b4c7-66123a24fa82", "roleState": "STARTED", "healthSummary": "GOOD"}]}

यदि आवश्यक हो, तो आप इसे मानव पठनीयता के लिए सुंदर प्रिंट के माध्यम से jqया json_ppउसके समान पाइप कर सकते हैं ।


1 perl में जर्स डेटा को पार्स करने और हेरफेर करने के लिए कई उत्कृष्ट मॉड्यूल हैं, इसलिए आप शायद उनमें से किसी एक का उपयोग करके बेहतर हैं। जब भी आप अपने आप को पाइपिंग डेटा से grep, sedऔर / या awkमें पाते हैं perl, तो आपको वास्तव में खुद से पूछना चाहिए "मैं ऐसा क्यों कर रहा हूं? यह पागल है, मुझे पूरी बात सिर्फ पर्ल में करनी चाहिए"। उसी के लिए कहा जा सकता है python


0

जैसा कि @ Theophrastus में बताया गया है, आप jqपहले JSON पार्सर को स्थापित करना चाहते हैं । उसके बाद, यह केवल आपके इच्छित मान के लिए फ़िल्टर करने की बात है।

मुझे यह उल्लेख करना चाहिए कि आपके द्वारा पोस्ट किया गया JSON ब्लॉक मान्य नहीं है; "आइटम" का प्रारंभिक ब्रैकेट बंद नहीं है, और दूसरी प्रविष्टि में itemsअल्पविराम विभाजक होना चाहिए। इसके बावजूद, मेरा मानना ​​है कि आपके पास एक मान्य ब्लॉक है, और केवल कट-एंड-पेस्ट किया गया है जो आपने सोचा था कि प्रासंगिक था। यदि प्रत्येक ब्लॉक वास्तव में प्रतिनिधि है, तो आपको सभी को जोड़ना होगा (यह मानकर bashकि आपका शेल है)

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

यह उन पंक्तियों को आउटपुट करेगा, जैसा कि निर्दिष्ट किया गया है, मान लें कि Your_JSON_BLOCK आपके डेटा के साथ पूर्ण वैध json स्ट्रिंग है।


0

हाल ही में मैं एक आसान यूनिक्स / शेल विकल्प के साथ आया हूं (यह पूरी तरह से FOSS और नि: शुल्क है) जैसे जोसन प्रश्नों से निपटने के लिए - एक नज़र डालें jtc। उपकरण को रिश्तेदार चलने से रोकते हैं (यानी एक को ढूंढना और फिर दूसरे को ऑफसेट करना)।

यह मानते हुए कि आपका मूल जसन नियत है (इसमें कुछ मुद्दे हैं), फिर क्ली इस तरह होगा:

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

0

[एक और jq दृष्टिकोण] यदि आप jq का उपयोग करते हैं तो यह वस्तुतः एक लाइनर है!

cat input.json | jq -r '.["items"] | map(select(.name | contains("first-block"))) | .[].hostRef.hostId'

पुनश्च

  1. jq कमांड बहुत आत्म व्याख्यात्मक हैं, इसलिए मैं अभी भी इसे समझाने का प्रयास नहीं कर रहा हूँ अगर किसी को कठिनाई का सामना करना पड़ रहा है तो मुझे टिप्पणियों में बताएं, मैं समझाऊंगा!

  2. प्रश्न में प्रदान किया गया जसन पूरा नहीं हुआ है!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.