JSON को पार्स करने के लिए - एक बैश स्क्रिप्ट के भीतर पायथन फ़ंक्शन का उपयोग करना

मेरे पास एक बैश स्क्रिप्ट है जिसका उद्देश्य जेएसओएन स्वरूपित डेटा को पार्स करना है। मैंने इस मंच पर एक पूर्व प्रश्न से सीखा है कि जेएसओएन पार्सिंग में बैश अच्छा नहीं है, और इसलिए पार्सिंग करने के लिए एक पायथन फ़ंक्शन का उपयोग करना चाहते हैं:

कोड स्निपेट निम्नलिखित है:

#!/bin/bash

set -e

declare -a data_id
declare -a data_tid

function parse_data() {
    python <

'जेसन' में संग्रहीत डेटा इस तरह दिखेगा:

{
    "cid": "1",
    "code": null,
    "error": null,
    "params": {
        "children": [
            {
                "value": {
                    "id": "0123456789",
                    "tid": "a.b.c"
                },
                "data": {
                    "id": "0987654321",
                    "tid": "p.q.r"
                },
                "tid": "m.n.o.p",
            }
        ],
        "tid": "m.n.o.p"
    },
    "reason": null,
    "result": true
}

मैं चाहता हूं कि स्क्रिप्ट 'आईडी' और 'tid' फ़ील्ड को 'डेटा' के नीचे से अलग सरणी में निकालने में सक्षम हो। लेकिन स्क्रिप्ट निष्पादन निम्नानुसार विफल रहता है:

[email protected]# ./abc.sh 
Traceback (most recent call last):
  File "", line 7, in 
TypeError: string indices must be integers

क्या गलत है पर कोई विचार?

0
@chepner: कार्य को आवश्यक है कि स्क्रिप्ट को बैश में लिखा जाए।
जोड़ा लेखक Maddy, स्रोत
@RemcoGerlich: मैंने पहले से ही एक लापता कॉमा को सही किया है; शायद एक बोट कॉपी कॉपी पेस्ट। मैंने अतिरिक्त चाबियाँ हटा दीं।
जोड़ा लेखक Martijn Pieters, स्रोत
उस JSON में कोई समस्या है: कुंजी 'मान', 'डेटा' और 'tid' सभी एक ही ऑब्जेक्ट में एक से अधिक बार प्रकट होते हैं। यह काम नहीं करेगा।
जोड़ा लेखक RemcoGerlich, स्रोत
अपने फ़ंक्शन का आह्वान करते समय उद्धरण जोड़ने का प्रयास करें: parse_data "$ json"
जोड़ा लेखक devnull, स्रोत
क्या पाइथन में पूरी लिपि नहीं लिखने के लिए कोई अनिवार्य कारण है?
जोड़ा लेखक chepner, स्रोत
जोड़ा लेखक Michael Kropat, स्रोत

4 उत्तर

यह रेखा:

fयाchild in parsed['params']['children'][0]:
    ...

parsed['params']['children'][0] is not a list.

इसे या तो बदलें

fयाchild in parsed['params']['children']:
    ...

या

# this one only fयाtesting
fयाchild in [parsed['params']['children'][0]]:
    ...

या

# also fयाtesting
child = parsed['params']['children'][0]
0
जोड़ा

[0] की छोड़ दें:

for child in parsed['params']['children']:

अन्यथा आप बच्चों सूची में पहली प्रविष्टि की कुंजी पर लूपिंग कर रहे हैं।

वैकल्पिक रूप से, यदि उस सूची में केवल एक प्रविष्टि है, तो लूप न करें, लेकिन सीधे असाइन करें:

child = parsed['params']['children'][0]
print 'id: %s' % (child['data']['id'])
port_id.append(child['data']['id'])
print 'tid: %s' % (child['data']['tid'])
port_tid.append(child['data']['tid'])
0
जोड़ा
अंत में [0] को अनदेखा करते हुए समस्या हल हो गई। धन्यवाद!
जोड़ा लेखक Maddy, स्रोत
मैंने देखा कि मान एरे डेटा_आईडी और डेटा_टिड में शामिल नहीं हैं, हालांकि प्रिंट ठीक काम करते हैं। सरणी का आकार शून्य दिखाया गया है।
जोड़ा लेखक Maddy, स्रोत
क्या कोई रास्ता नहीं है? क्या वे स्क्रिप्ट में सह-अस्तित्व में नहीं हैं और डेटा साझा कर सकते हैं?
जोड़ा लेखक Maddy, स्रोत
@ मैडी: क्या आप पाइथन सूचियों को अपने बैश सरणी के बारे में जानने की उम्मीद कर रहे हैं? वह बिल्कुल काम नहीं करेगा। Subprocesses के पास बैश चर के लिए उपयोग नहीं है; आपको पायथन प्रक्रिया को stdout या stderr पर लिखना होगा, अपनी बैश स्क्रिप्ट में कैप्चर करें और वहां से जाएं।
जोड़ा लेखक Martijn Pieters, स्रोत
नहीं, बैश इसकी विस्तारशीलता के लिए ज्ञात नहीं है। पायथन एक उपप्रोसेसर के रूप में चलाया जाता है, इसके पास मूल प्रक्रिया की स्मृति तक कोई पहुंच नहीं है, बिना किसी स्पष्ट संदेश के गुजरने के।
जोड़ा लेखक Martijn Pieters, स्रोत
सबकुछ को इसके बजाय एक पायथन स्क्रिप्ट पर क्यों नहीं ले जाएं? इससे कम से कम उस समस्या को हल करने की आवश्यकता को हटा दिया जाएगा।
जोड़ा लेखक Martijn Pieters, स्रोत

आप केवल बच्चों की सूची के पहले आइटम का जिक्र कर रहे हैं। तो "बच्चा" वास्तव में शब्दकोश की कुंजी है।

आपको फॉर लूप से [0] को हटा देना चाहिए

0
जोड़ा

अगर आप पाइथन लिपि लिखते हैं तो आपको डीबग करना इतना आसान लगेगा, फिर इसे बैश स्क्रिप्ट में एम्बेड करने का प्रयास किया। डीबग संस्करण है:

import json, sys

parsed = json.load(sys.stdin)

port_id = []
port_tid = []
for child in parsed['params']['children']:
    print 'id: %s' % (child['data']['id'])
    port_id.append(child['data']['id'])
    print 'tid: %s' % (child['data']['tid'])
    port_tid.append(child['data']['tid'])

दूसरा, आपके पास अपने जेसन डेटा में एक बग है। मुझे लगता है कि आप इसका मतलब था:

{
    "cid": "1",
    "code": null,
    "error": null,
    "params": {
        "children": [
            {
                "value": {
                    "id": "0123456789",
                    "tid": "a.b.c"
                },
                "data": {
                    "id": "0987654321",
                    "tid": "p.q.r"
                },
                "tid": "m.n.o.p"
            },
            {
               "value": {
                    "id": "0987654321",
                    "tid": "a.b.c"
                },
                "data": {
                    "id": "0123456789",
                    "tid": "p.q.r"
                },
                "tid": "m.n.o.p"
            }
        ],
        "tid": "m.n.o.p"
    },
    "reason": null,
    "result": true
}

अंत में, आपको अभी भी अपने बैश सरणी में आउटपुट लोड करने की आवश्यकता है। मेरा समाधान यहाँ है:

#!/bin/bash

set -e

parse_ids() { python -c '
import json, sys
parsed = json.load(sys.stdin)
print u"\n".join(c["data"]["id"] for c in parsed["params"]["children"])'
}

parse_tids() { python -c '
import json, sys
parsed = json.load(sys.stdin)
print u"\n".join(c["data"]["tid"] for c in parsed["params"]["children"])'
}

#json=$(get_json_output)
json=$(
0
जोड़ा