पार्सन जेन्स पायथन का उपयोग कर?


18

मेरे पास members.jsonनीचे एक JSON फाइल है ।

{
   "took": 670,
   "timed_out": false,
   "_shards": {
      "total": 8,
      "successful": 8,
      "failed": 0
   },
   "hits": {
      "total": 74,
      "max_score": 1,
      "hits": [
         {
            "_index": "2000_270_0",
            "_type": "Medical",
            "_id": "02:17447847049147026174478:174159",
            "_score": 1,
            "_source": {
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcf",
               "memberFirstName": "Uri",
               "memberMiddleName": "Prayag",
               "memberLastName": "Dubofsky"
            }
         }, 
         {
            "_index": "2000_270_0",
            "_type": "Medical",
            "_id": "02:17447847049147026174478:174159",
            "_score": 1,
            "_source": {
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcG",
               "memberFirstName": "Uri",
               "memberMiddleName": "Prayag",
               "memberLastName": "Dubofsky"
            }
         }
      ]
   }
}

मैं bashस्क्रिप्ट का उपयोग करके इसे पार्स करना चाहता हूं केवल क्षेत्र की सूची प्राप्त करें memberId

अपेक्षित आउटपुट है:

memberIds
----------- 
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG

मैंने निम्नलिखित बैश + अजगर कोड को जोड़ने की कोशिश की .bashrc:

function getJsonVal() {
   if [ \( $# -ne 1 \) -o \( -t 0 \) ]; then
       echo "Usage: getJsonVal 'key' < /tmp/file";
       echo "   -- or -- ";
       echo " cat /tmp/input | getJsonVal 'key'";
       return;
   fi;
   cat | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["'$1'"]';
}

और फिर बुलाया:

$ cat members.json | getJsonVal "memberId"

लेकिन यह फेंकता है:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
KeyError: 'memberId'

संदर्भ

/programming//a/21595107/432903


2
आपको बैश में ऐसा करने की आवश्यकता क्यों है? आप यहां स्पष्ट रूप से अजगर का उपयोग कर रहे हैं तो क्यों न केवल एक अजगर स्क्रिप्ट बनाएं जो काम करता है? आपको इसे बाश के साथ करने के बारे में वास्तविक जवाब नहीं मिल सकता है क्योंकि जब आपको ऐसा करने की आवश्यकता होती है तो आप दूसरी भाषा का उपयोग करते हैं।
डेविड एफजी

मैं से अपने शीर्षक बदल "बैश स्क्रिप्ट का उपयोग" के लिए "अजगर का उपयोग कर" के बाद से python, और नहीं bash, क्या आप पार्स json के लिए उपयोग कर रहे हैं। उदाहरण के लिए, वह त्रुटि निश्चित रूप से एक अजगर त्रुटि है, न कि कोई त्रुटि।
गोल्डीलॉक्स

@goldilocks सिर्फ इसलिए कि उनके प्रयास का इस्तेमाल किया python, इसका मतलब यह नहीं है कि उनका लक्ष्य का उपयोग करना हैpython
jordanm

@ दाविदजी मेरा जवाब देखें। यह शुद्ध शेल नहीं है, यह एक बाहरी कमांड है लेकिन यह शेल स्क्रिप्ट में बहुत अच्छी तरह से एकीकृत होता है।
जोर्डन

क्या मैं आपको सुझाव दे सकता हूं कि आप ज्यादातर अप्रासंगिक क्षेत्रों को निकाल सकते हैं। यह करने के लिए कि आप क्या करने की कोशिश करते हैं, इसका सार पाने के लिए _source में 2-3 तत्व होते हैं। बाकी बस ध्यान भंग करता है
एंथन

जवाबों:


25

यदि आप उपयोग करेंगे:

 $ cat members.json | \
     python -c 'import json,sys;obj=json.load(sys.stdin);print obj;'

आप नेस्टेड तानाशाह की संरचना का निरीक्षण कर सकते हैं objऔर देख सकते हैं कि आपकी मूल पंक्ति को पढ़ना चाहिए:

$ cat members.json | \
    python -c 'import json,sys;obj=json.load(sys.stdin);print obj["hits"]["hits"][0]["_source"]["'$1'"]';

उस "में सदस्य" तत्व को। इस तरह आप पायथन को ऑनलाइनर के रूप में रख सकते हैं।

यदि नेस्टेड "हिट" तत्व में कई तत्व हैं, तो आप कुछ ऐसा कर सकते हैं:

$ cat members.json | \
python -c '
import json, sys
obj=json.load(sys.stdin)
for y in [x["_source"]["'$1'"] for x in obj["hits"]["hits"]]:
    print y
'

किसी भी स्तर पर (अद्वितीय) कुंजियों के लिए एकल मान खोजने के लिए क्रिस डाउन का समाधान बेहतर है।

मेरे दूसरे उदाहरण के साथ, जो कई मानों को प्रिंट करता है, आप एक लाइनर के साथ जो भी प्रयास करना चाहिए, उसकी सीमाएं मार रहे हैं, उस बिंदु पर मुझे बहुत कम कारण दिखाई देते हैं कि आधे प्रसंस्करण को बाश में क्यों करना है, और एक पूर्ण पायथन समाधान के लिए कदम होगा ।


8

बैश में ऐसा करने का एक और तरीका jshon है । यहाँ आपकी समस्या का समाधान दिया गया है jshon:

$ jshon -e hits -e hits -a -e _source -e memberId -u < foo.json
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG

-eविकल्प json से मान एक्सट्रैक्ट। -aसरणी पर iterates और -uअंतिम स्ट्रिंग डीकोड।


मुझे jshon
प्रयागपाद

6

ठीक है, आपकी कुंजी काफी स्पष्ट रूप से वस्तु के मूल में नहीं है। कुछ इस तरह की कोशिश करो:

json_key() {
    python -c '
import json
import sys

data = json.load(sys.stdin)

for key in sys.argv[1:]:
    try:
        data = data[key]
    except TypeError:  # This is a list index
        data = data[int(key)]

print(data)' "$@"
}

इससे सिर्फ़ सिंटैक्स को पाइथन में इंजेक्ट करने का ही लाभ नहीं है, जो टूटने (या बदतर, मनमाने कोड निष्पादन) का कारण बन सकता है।

तब आप इसे इस तरह से कॉल कर सकते हैं:

json_key hits hits 0 _source memberId < members.json

1
नोट: यह "हिट" में प्रत्येक आइटम पर लूप नहीं करेगा। यदि आप ऐसा चाहते हैं, तो आपको उस उदाहरण के लिए विशिष्ट पायथन कोड लिखना चाहिए।
क्रिस डाउन

लेकिन यह केवल एक ही सदस्य दिखाता है।
प्रयागपाद

4

एक अन्य विकल्प है JQ :

$ cat members.json | jq -r '.hits|.hits|.[]|._source|.memberId'
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG

2

इसे इस्तेमाल करे:

$ cat json.txt | python -c 'import sys; import simplejson as json; \
print "\n".join( [i["_source"]["memberId"] for i in json.loads( sys.stdin.read() )["hits"]["hits"]] )'


यदि आपके पास पहले से ही pretty printedजसन है, तो आप grepइसे क्यों नहीं करते ?

$ cat json.txt | grep memberId
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcf",
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcG",

आप हमेशा सिंपलसन पायथन के साथ एक सुंदर मुद्रित प्रारूप प्राप्त कर सकते हैं grep

# cat json_raw.txt
{"hits": {"hits": [{"_score": 1, "_type": "Medical", "_id": "02:17447847049147026174478:174159", "_source": {"memberLastName": "Dubofsky", "memberMiddleName": "Prayag", "memberId": "0x7b93910446f91928e23e1043dfdf5bcf", "memberFirstName": "Uri"}, "_index": "2000_270_0"}, {"_score": 1, "_type": "Medical", "_id": "02:17447847049147026174478:174159", "_source": {"memberLastName": "Dubofsky", "memberMiddleName": "Prayag", "memberId": "0x7b93910446f91928e23e1043dfdf5bcG", "memberFirstName": "Uri"}, "_index": "2000_270_0"}], "total": 74, "max_score": 1}, "_shards": {"successful": 8, "failed": 0, "total": 8}, "took": 670, "timed_out": false}

डंप का उपयोग करें:

# cat json_raw.txt | python -c 'import sys; import simplejson as json; \
print json.dumps( json.loads( sys.stdin.read() ), sort_keys=True, indent=4); '

{
    "_shards": {
        "failed": 0,
        "successful": 8,
        "total": 8
    },
    "hits": {
        "hits": [
            {
                "_id": "02:17447847049147026174478:174159",
                "_index": "2000_270_0",
                "_score": 1,
                "_source": {
                    "memberFirstName": "Uri",
                    "memberId": "0x7b93910446f91928e23e1043dfdf5bcf",
                    "memberLastName": "Dubofsky",
                    "memberMiddleName": "Prayag"
                },
                "_type": "Medical"
            },
            {
                "_id": "02:17447847049147026174478:174159",
                "_index": "2000_270_0",
                "_score": 1,
                "_source": {
                    "memberFirstName": "Uri",
                    "memberId": "0x7b93910446f91928e23e1043dfdf5bcG",
                    "memberLastName": "Dubofsky",
                    "memberMiddleName": "Prayag"
                },
                "_type": "Medical"
            }
        ],
        "max_score": 1,
        "total": 74
    },
    "timed_out": false,
    "took": 670
}

इसके बाद, बस grep'मेम्बरड' पैटर्न के साथ परिणाम।

पूरी तरह से सटीक होने के लिए:

#!/bin/bash

filename="$1"
cat $filename | python -c 'import sys; import simplejson as json; \
print json.dumps( json.loads( sys.stdin.read() ), sort_keys=True, indent=4)' | \
grep memberId | awk '{print $2}' | sed -e 's/^"//g' | sed -e 's/",$//g'

उपयोग:

$ bash bash.sh json_raw.txt 
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG


0

डीपडिफ़ के उपयोग से आपको सटीक कुंजियों को जानने की आवश्यकता नहीं है:

import json
from deepdiff import DeepSearch
DeepSearch(json.load(open("members.json", "r")), 'memberId', verbose_level=2)['matched_paths'].values()

0

यहाँ एक बैश समाधान है।

  1. फ़ाइल बनाएँ find_members.sh
  2. फ़ाइल + सेव करने के लिए निम्न लाइन जोड़ें

    #!/bin/bash
    
    echo -e "\nmemberIds\n---------"
    cat members.json | grep -E 'memberId'|awk '{print$2}' | cut -d '"' -f2
    
  3. chmod +x find_members.sh

अब इसे चलाएं:

$ ./find_members.sh

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