Unix टूल्स के साथ JSON को पार्स करना


877

मैं JSON को कर्ल अनुरोध से लौटाने की कोशिश कर रहा हूं, जैसे:

curl 'http://twitter.com/users/username.json' |
    sed -e 's/[{}]/''/g' | 
    awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'

उपरोक्त JSON को खेतों में विभाजित करता है, उदाहरण के लिए:

% ...
"geo_enabled":false
"friends_count":245
"profile_text_color":"000000"
"status":"in_reply_to_screen_name":null
"source":"web"
"truncated":false
"text":"My status"
"favorited":false
% ...

मैं एक विशिष्ट क्षेत्र (द्वारा चिह्नित -v k=text) कैसे प्रिंट कर सकता हूं ?


5
ईआरएम जो कि अच्छा json पार्सिंग btw नहीं है ... स्ट्रिंग्स में भागने के पात्रों के बारे में क्या है ... आदि तो एसओ पर एक पायथन का जवाब है (एक पर्ल जवाब भी ...)?
शहीद

51
किसी भी समय कोई भी कहता है "समस्या एक्स को आसानी से अन्य भाषा वाई के साथ हल किया जा सकता है," इसके लिए कोड है "मेरे टूलबॉक्स में केवल नाखून ड्राइविंग के लिए एक चट्टान है ... कुछ और क्यों परेशान करता है?"
ब्रायनह

22
@BryanH: कभी-कभी भाषा को छोड़कर, Y विशेष रूप से समस्या को हल करने के लिए अधिक सुसज्जित हो सकता है, चाहे वह व्यक्ति कितनी भी भाषाओं में Y को सुझाता हो।
JFS

14
किंदा देर से, लेकिन यहाँ यह हो जाता है। grep -Po '"'"version"'"\s*:\s*"\K([^"]*)' package.json। यह आसानी से और केवल grep के साथ कार्य को हल करता है और सरल JSONs के लिए पूरी तरह से काम करता है। जटिल JSONs के लिए आपको उचित पार्सर का उपयोग करना चाहिए।
डायोसनी

2
@auser, क्या आप शीर्षक में "sed और awk के साथ" को "UNIX टूल्स के साथ" बदलते हुए संपादित करना ठीक रहेगा?
22

जवाबों:


1125

कमांड लाइन से JSON में हेरफेर करने के उद्देश्य से विशेष रूप से डिज़ाइन किए गए कई उपकरण हैं, और यह Awk के साथ करने की तुलना में बहुत आसान और अधिक विश्वसनीय होगा, जैसे jq:

curl -s 'https://api.github.com/users/lambda' | jq -r '.name'

आप इसे उन उपकरणों के साथ भी कर सकते हैं जो आपके सिस्टम पर पहले से इंस्टॉल हैं, जैसे कि jsonमॉड्यूल का उपयोग करते हुए पायथन , और इसलिए किसी भी अतिरिक्त निर्भरता से बचें, जबकि अभी भी एक उचित JSON पार्सर का लाभ है। निम्नलिखित मान लें कि आप UTF-8 का उपयोग करना चाहते हैं, जिसे मूल JSON में एन्कोड किया जाना चाहिए और सबसे आधुनिक टर्मिनल भी हैं:

अजगर 3:

curl -s 'https://api.github.com/users/lambda' | \
    python3 -c "import sys, json; print(json.load(sys.stdin)['name'])"

अजगर 2:

export PYTHONIOENCODING=utf8
curl -s 'https://api.github.com/users/lambda' | \
    python2 -c "import sys, json; print json.load(sys.stdin)['name']"

ऐतिहासिक नोट

यह उत्तर मूल रूप से अनुशंसित jsawk है , जो अभी भी काम करना चाहिए, लेकिन उपयोग करने के लिए थोड़ा अधिक बोझिल है jq, और एक स्टैंडअलोन जावास्क्रिप्ट दुभाषिया पर निर्भर करता है जो कि पायथन दुभाषिया की तुलना में कम सामान्य है, इसलिए उपरोक्त उत्तर संभवतः बेहतर हैं:

curl -s 'https://api.github.com/users/lambda' | jsawk -a 'return this.name'

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

curl 'http://twitter.com/users/username.json' | jq -r '.text'

7
@thrau +1। jq यह रिपॉजिटरी में उपलब्ध है और उपयोग करने के लिए सुपर आसान है इसलिए यह jsawk से बहुत बेहतर है। मैंने कुछ मिनटों के लिए दोनों का परीक्षण किया, jq ने यह लड़ाई जीती
सिजोन सैडलो

1
ध्यान दें कि पायथन 2 में, यदि आप आउटपुट को किसी अन्य कमांड पर पाइप कर रहे हैं, तो printकथन हमेशा ASCII को एन्कोड करेगा क्योंकि आप पाइप में पायथन का उपयोग कर रहे हैं। PYTHONIOENCODING=<desired codec>अपने टर्मिनल के लिए उपयुक्त एक अलग आउटपुट एन्कोडिंग सेट करने के लिए कमांड में डालें । पायथन 3 में, डिफ़ॉल्ट इस मामले में UTF-8 है ( print() फ़ंक्शन का उपयोग करके )।
मार्टिन पीटर्स

1
OSX पर स्थापित करें काढ़ा के
एंडी फ्रेली

1
curl -sके बराबर है curl --silent, जबकि jq -rइसका मतलब है jq --raw-outputबिना स्ट्रिंग उद्धरण के।
सर्ज स्ट्रोबंड्ट

अजगर-सी "आयात अनुरोध; r = request.get (' api.github.com/users/lambda');print r.json () [' नाम '];" । सबसे सरल!
NotTooTechy

276

किसी विशेष कुंजी के लिए मूल्यों को जल्दी से निकालने के लिए, मैं व्यक्तिगत रूप से "grep -o" का उपयोग करना पसंद करता हूं, जो केवल रेगेक्स के मैच को वापस करता है। उदाहरण के लिए, ट्वीट से "पाठ" फ़ील्ड प्राप्त करने के लिए, कुछ इस तरह है:

grep -Po '"text":.*?[^\\]",' tweets.json

यह रेगेक्स आपके विचार से अधिक मजबूत है; उदाहरण के लिए, यह एम्बेडेड कॉमा के साथ तार के साथ ठीक काम करता है और उनके अंदर उद्धरण बच गए। मुझे लगता है कि थोड़े और काम के साथ आप एक ऐसा बना सकते हैं जो वास्तव में मूल्य निकालने की गारंटी है, अगर यह परमाणु है। (यदि इसमें घोंसला है, तो एक रेगीक्स इसे निश्चित रूप से नहीं कर सकता है।)

और आगे साफ करने के लिए (स्ट्रिंग के मूल एस्केपिंग रखने यद्यपि) आप की तरह कुछ का उपयोग कर सकते हैं: | perl -pe 's/"text"://; s/^"//; s/",$//'। (मैंने इस विश्लेषण के लिए ऐसा किया है ।)

उन सभी नफरत करने वालों के लिए जो आपको एक असली JSON पार्सर का उपयोग करना चाहिए - हाँ, यह शुद्धता के लिए आवश्यक है, लेकिन

  1. वास्तव में त्वरित विश्लेषण करने के लिए, जैसे डेटा क्लीनिंग बग पर जांच करने के लिए मानों की गणना करना या डेटा के लिए एक सामान्य अनुभव प्राप्त करना, कमांड लाइन पर कुछ पीटना अधिक तेज़ है। एक स्क्रिप्ट लिखने के लिए एक संपादक खोलना विचलित करने वाला है।
  2. grep -oपायथन मानक jsonपुस्तकालय की तुलना में तेजी से परिमाण के आदेश हैं , कम से कम जब ट्वीट के लिए ऐसा करते हैं (जो कि ~ 2 केबी प्रत्येक हैं)। मुझे यकीन नहीं है कि यह सिर्फ इसलिए jsonहै क्योंकि यह धीमा है (मुझे कुछ समय के लिए यजल से तुलना करनी चाहिए); लेकिन सिद्धांत रूप में, एक रेगेक्स तेजी से होना चाहिए क्योंकि यह परिमित स्थिति है और बहुत अधिक अनुकूलन योग्य है, एक पार्सर के बजाय जिसे पुनरावृत्ति का समर्थन करना है, और इस मामले में, संरचनाओं के लिए बहुत सारे सीपीयू निर्माण पेड़ों को खर्च करता है जिनकी आपको परवाह नहीं है। (यदि किसी ने एक परिमित राज्य ट्रांसड्यूसर लिखा जो उचित (गहराई-सीमित) JSON पार्सिंग करता है, तो यह शानदार होगा! इस बीच हमारे पास "grep -o" है।)

मेंटेनेंस कोड लिखने के लिए, मैं हमेशा एक असली पार्सिंग लाइब्रेरी का उपयोग करता हूं। मैंने jsawk की कोशिश नहीं की है , लेकिन अगर यह अच्छी तरह से काम करता है, तो वह बिंदु # 1 को संबोधित करेगा।

एक अंतिम, निराला, समाधान: मैंने एक स्क्रिप्ट लिखी है जो पायथन का उपयोग करती है jsonऔर आपके द्वारा इच्छित कुंजी को टैब से अलग किए गए कॉलम में निकालती है; फिर मैं एक रैपर के माध्यम से पाइप करता हूं awkजो स्तंभों तक पहुंच की अनुमति देता है। यहाँ में: json2tsv और tsvawk स्क्रिप्ट । तो इस उदाहरण के लिए यह होगा:

json2tsv id text < tweets.json | tsvawk '{print "tweet " $id " is: " $text}'

यह दृष्टिकोण # 2 को संबोधित नहीं करता है, एक पायथन स्क्रिप्ट की तुलना में अधिक अक्षम है, और यह थोड़ा भंगुर है: यह स्ट्रिंग के मूल्यों में नईलाइन्स और टैब के सामान्यीकरण को मजबूर करता है, जो कि awk के क्षेत्र / रिकॉर्ड-सीमांकित दृश्य के साथ अच्छा खेलने के लिए है। लेकिन यह आपको कमांड लाइन पर अधिक शुद्धता के साथ रहने देता है grep -o


11
आप पूर्णांक मानों के बारे में भूल गए। grep -Po '"text":(\d*?,|.*?[^\\]",)'
रॉबर्ट

3
रॉबर्ट: ठीक है, मेरे regex केवल उस क्षेत्र के लिए स्ट्रिंग मानों के लिए लिखा गया था। जैसा कि आप कहते हैं, इंटेगर को जोड़ा जा सकता है। यदि आप सभी प्रकार चाहते हैं, तो आपको अधिक से अधिक करना होगा: बूलियन, अशक्त। और सरणियों और वस्तुओं को अधिक काम करने की आवश्यकता होती है; केवल गहराई-सीमित मानक रीगेक्स के तहत संभव है।
ब्रेंडन OConnor

9
1. jq .nameकमांड-लाइन पर काम करता है और इसके लिए "स्क्रिप्ट लिखने के लिए संपादक खोलने" की आवश्यकता नहीं होती है। 2. इससे कोई फर्क नहीं पड़ता कि आपका रेगेक्स कितनी तेजी से गलत परिणाम उत्पन्न कर सकता है
20:24 बजे

6
और यदि आप केवल उन मूल्यों को चाहते हैं जिन्हें आप केवल उस पर फेंक सकते हैं। | grep -Po '"text":.*?[^\\]",'|awk -F':' '{print $2}'
जेफ क्रैटर

34
ऐसा लगता है कि OSX पर -Pविकल्प गायब है। मैंने OSX 10.11.5 पर परीक्षण किया और grep --versionथा grep (BSD grep) 2.5.1-FreeBSD। मुझे यह OSX पर "विस्तारित रेगेक्स" विकल्प के साथ काम करने में मिला। ऊपर से कमान होगी grep -Eo '"text":.*?[^\\]",' tweets.json
जेन्स

174

इस आधार पर कि यहाँ कुछ सिफारिशों (टिप्पणियों में esp) ने पायथन के उपयोग का सुझाव दिया, मुझे एक उदाहरण नहीं मिलने से निराशा हुई।

तो, यहाँ कुछ JSON डेटा से एकल मान प्राप्त करने के लिए एक लाइनर है। यह मानता है कि आप (कहीं से) डेटा को पाइप कर रहे हैं और इसलिए इसे स्क्रिप्टिंग संदर्भ में उपयोगी होना चाहिए।

echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["hostname"]'

मैंने बैश फ़ंक्शन का उपयोग करने के लिए नीचे इस उत्तर को बढ़ाया: कर्ल 'some_api' | GetJsonVal 'की'
जो हेमिंग

pythonpy( github.com/russell91/pythonpy लगभग हमेशा एक बेहतर विकल्प होता है python -c, हालांकि इसे पाइप के साथ स्थापित करना पड़ता है। बस py --ji -x 'x[0]["hostname"]'जिप्स को पाइप करें । यदि आप json_input समर्थन में बिल्ट का उपयोग नहीं करना चाहते हैं, तो आप अभी भी प्राप्त कर सकते हैं। वे स्वचालित रूप से आयात करते हैंpy 'json.loads(sys.stdin)[0]["hostname"]'
रसेलस्टवर्ट

2
धन्यवाद! अधिक त्वरित और गंदे JSON पार्सिंग के लिए, मैंने इसे एक bash फ़ंक्शन में लपेटा है: jsonq() { python -c "import sys,json; obj=json.load(sys.stdin); print($1)"; }ताकि मैं लिख सकूं: curl ...... | jsonq 'json.dumps([key["token"] for key in obj], indent=2)'और इसी तरह के डरावने सामान ... Btw, obj[0]अनावश्यक लगता है, यह दिखता है कि objडिफ़ॉल्ट मामलों में ठीक काम करता है? (?)।
अंकल

धन्यवाद। मैंने JSON को प्रिंट की तुलना में थोड़ा बेहतर बनाया है:jsonq() { python -c "import sys,json; obj=json.load(sys.stdin); sys.stdout.write(json.dumps($1))"; }
एडम के डीन

4
obj[0]पार्स करते समय कोई त्रुटि होती है { "port":5555 }। हटाने के बाद ठीक काम करता है [0]
साइबरएड

134

मार्टिन और बोएको के नेतृत्व के बाद:

$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool

जो आपको एक बेहद शानदार फ्रेंडली आउटपुट देगा। बहुत ही सुविधाजनक:

$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool | grep my_key

37
आप एक विशिष्ट कुंजी कैसे निकालेंगे, जैसा कि ओपी पूछ रहा है?
जुआन

2
सबसे अच्छा जवाब अब तक imho, सबसे distros पर कुछ और स्थापित करने की कोई जरूरत नहीं है और आप कर सकते हैं | grep field। धन्यवाद!
एंड्रिया रिचियार्डी

7
यह सब JSON प्रारूपित है, अगर मैं गलत नहीं हूँ। यह आउटपुट से किसी विशेष क्षेत्र का चयन करने की अनुमति नहीं देता है, जैसा कि एक xpath समाधान होगा, या "JSON पॉइंटर" पर आधारित कुछ।
चेसो

4
मैं सिर्फ एक महत्वपूर्ण मूल्य जोड़ी के साथ समाप्त होता हूं, लेकिन स्वयं के मूल्य में नहीं।
क्रिस्टोफर

1
jqआमतौर पर अजगर स्थापित नहीं होता है। इसके अलावा, पायथन में एक बार आप पूरे रास्ते से जा सकते हैं और इसे पार्स कर सकते हैंimport json...
CpILL

125

आप अपने प्लेटफॉर्म के लिए बाइनरी डाउनलोडjq कर सकते हैं और चला सकते हैं ( chmod +x jq):

$ curl 'https://twitter.com/users/username.json' | ./jq -r '.name'

यह "name"json ऑब्जेक्ट से विशेषता निकालता है ।

jqहोमपेज कहता है कि यह sedJSON डेटा के लिए है।


27
सिर्फ रिकॉर्ड के लिए, jqएक अद्भुत उपकरण है।
होस

2
माना। मैं स्वीकृत उत्तर से jsawk के साथ तुलना नहीं कर सकता, क्योंकि मैंने इसका उपयोग नहीं किया है, लेकिन स्थानीय प्रयोग के लिए (जहां एक उपकरण स्थापित करना स्वीकार्य है) मैं अत्यधिक jq की सलाह देता हूं। यहाँ एक और अधिक व्यापक उदाहरण दिया गया है, जो एक सरणी के प्रत्येक तत्व को लेता है और चयनित डेटा के साथ एक नई JSON ऑब्जेक्ट को संश्लेषित करता है: curl -s https://api.example.com/jobs | jq '.jobs[] | {id, o: .owner.username, dateCreated, s: .status.state}'
jbyler

2
इसे प्रेम करें। बहुत हल्का वजन, और चूंकि यह सादे पुराने सी में है, इसे बस कहीं भी संकलित किया जा सकता है।
बेन्मज

1
सबसे व्यावहारिक एक: इसे तीसरे पक्ष के पुस्तकालयों की आवश्यकता नहीं है (जबकि jsawk करता है) और स्थापित करने के लिए आसान है (OSX: काढ़ा स्थापित करें
jq

1
यह मेरे उपयोग के मामले के लिए सबसे व्यावहारिक और आसानी से लागू होने वाला उत्तर है। उबंटू (14.04) सिस्टम के लिए एक सरल apt-get install jq ने टूल को मेरे सिस्टम में जोड़ा। मैं JWS आउटपुट JWS से JWS में jq आउटपुट दे रहा हूं और यह प्रतिक्रिया में निहित कुछ कुंजी के मान निकालने के लिए बहुत अच्छा काम करता है।
ब्रेंडन के

105

Node.js का उपयोग करना

अगर सिस्टम है स्थापित, -pप्रिंट और -eफ्लैगशिप स्क्रिप्ट का उपयोग करना संभव है JSON.parseजो किसी भी मूल्य को खींचने के लिए आवश्यक है।

JSON स्ट्रिंग का उपयोग करके एक सरल उदाहरण { "foo": "bar" }और "फू" के मूल्य को बाहर निकालना:

$ node -pe 'JSON.parse(process.argv[1]).foo' '{ "foo": "bar" }'
bar

क्योंकि हमारे पास catऔर अन्य उपयोगिताओं तक पहुंच है , हम इसका उपयोग फ़ाइलों के लिए कर सकते हैं:

$ node -pe 'JSON.parse(process.argv[1]).foo' "$(cat foobar.json)"
bar

या किसी अन्य प्रारूप जैसे कि URL जिसमें JSON हो:

$ node -pe 'JSON.parse(process.argv[1]).name' "$(curl -s https://api.github.com/users/trevorsenior)"
Trevor Senior

1
धन्यवाद! लेकिन मेरे मामले में यह केवल -e ध्वज के साथ काम कर रहा हैnode -p -e 'JSON.parse(process.argv[1]).foo' '{ "foo": "bar" }'
Rnd_d

33
पाइप्स! curl -s https://api.github.com/users/trevorsenior | node -pe "JSON.parse(require('fs').readFileSync('/dev/stdin').toString()).name"
नेसरोबोट

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

यह बैश स्क्रिप्ट फ़ंक्शन है: # jsonv को एक विशिष्ट विशेषता के लिए json ऑब्जेक्ट मान मिलता है। # पहला पैरामीटर json दस्तावेज़ है # दूसरा पैरामीटर वह विशेषता है जिसे मान get_json_attribute_value () {नोड -pe-JSON.parse (प्रक्रिया) को लौटाया जाना चाहिए। argv [1]) [process.argv [२]] '"$ 1" "$ 2"}
Youness

6
Node.js 10 के साथ निम्नलिखित काम करता है:cat package.json | node -pe 'JSON.parse(fs.readFileSync(0)).version'
Ilya Boyandin

100

उपयोग अजगर के JSON समर्थन बजाय awk का उपयोग करने का!

कुछ इस तरह:

curl -s http://twitter.com/users/username.json | \
    python -c "import json,sys;obj=json.load(sys.stdin);print obj['name'];"

6
मुझे एक अच्छी प्रतिक्रिया के साथ आने की कोशिश करने के लिए क्षमा करें ...: मैं कड़ी मेहनत करने की कोशिश करूंगा। पक्षपात के लिए इसे हटाने के लिए एक अचूक स्क्रिप्ट लिखने से अधिक आवश्यकता होती है!
मार्टिंक

9
तुम उस oneliner समाधान में obj चर का उपयोग क्यों करते हैं ?. यह बेकार है और वैसे भी संग्रहीत नहीं है? आपको कम का उपयोग कर लिखने json.load(sys.stdin)['"key']"की तरह उदाहरण के रूप में: curl -sL httpbin.org/ip | python -c "import json,sys; print json.load(sys.stdin)['origin']"
m3nda

64

आपने पूछा कि खुद को पैर में कैसे मारना है और मैं यहां बारूद उपलब्ध करा रहा हूं:

curl -s 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^text/ {print $2}'

आप tr -d '{}'इसके बजाय उपयोग कर सकते हैं sed। लेकिन उन्हें पूरी तरह से छोड़ने से वांछित प्रभाव पड़ता है।

यदि आप बाहरी उद्धरणों को अलग करना चाहते हैं, तो उपरोक्त के परिणाम को पाइप करें sed 's/\(^"\|"$\)//g'

मुझे लगता है कि अन्य लोगों ने पर्याप्त अलार्म लगाया है। मैं एक एम्बुलेंस को कॉल करने के लिए एक सेल फोन के साथ खड़ा हूँ। तैयार होते ही गोली दागना।


10
इस तरह पागलपन झूठ है, इसे पढ़ें: stackoverflow.com/questions/1732348/…
आगे की सूचना तक रोक दिया गया।

3
मैंने सभी उत्तरों को पढ़ा है और यह मेरे लिए बिना किसी अतिरिक्त निर्भरता के पूरी तरह से काम करता है। +1
eth0

यही मैं ढूंढ रहा था। एकमात्र सुधार - उद्धरण चिह्नों को हटाने के लिए sed कमांड मेरे लिए
कारगर

44

पाइथन के साथ बैश का उपयोग करना

अपने .bash_rc फ़ाइल में एक बैश फ़ंक्शन बनाएँ

function getJsonVal () { 
    python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1))"; 
}

फिर

$ curl 'http://twitter.com/users/username.json' | getJsonVal "['text']"
My status
$ 

यहाँ एक ही फ़ंक्शन है, लेकिन त्रुटि जाँच के साथ।

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

जहां $ # -ne 1 कम से कम 1 इनपुट सुनिश्चित करता है, और -t 0 सुनिश्चित करें कि आप एक पाइप से रीडायरेक्ट कर रहे हैं।

इस कार्यान्वयन के बारे में अच्छी बात यह है कि आप नेस्टेड जोंस मूल्यों का उपयोग कर सकते हैं और बदले में जसन प्राप्त कर सकते हैं! =)

उदाहरण:

$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' |  getJsonVal "['foo']['a'][1]"
2

यदि आप वास्तव में फैंसी बनना चाहते हैं, तो आप डेटा को बहुत प्रिंट कर सकते हैं:

function getJsonVal () { 
    python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1, sort_keys=True, indent=4))"; 
}

$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' |  getJsonVal "['foo']"
{
    "a": [
        1, 
        2, 
        3
    ], 
    "bar": "baz"
}

बैश फंक्शन के बिना वन-लाइनर:curl http://foo | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["environment"][0]["name"]'
चीज़ो

1
sys.stdout.write()यदि आप चाहते हैं कि यह अजगर 2 और 3 के साथ काम करे
प्रति जोहानसन

मैं सोच रहा हूं कि इसे system.stdout.write (obj $ 1) में बदलना चाहिए। इस तरह से आप कह सकते हैं: getJsonVal "['पर्यावरण'] ['नाम']", जैसे @Cheeso का उदाहरण
जो हेमिंग

1
@Narek उस मामले में, यह इस तरह दिखेगा: फ़ंक्शनgetJsonVal() { py -x "json.dumps(json.loads(x)$1, sort_keys=True, indent=4)"; }
जो हेमिंग सेप 22'16

30

टिकटी एक JSON पार्सर है जो बैश में लिखा है (<कोड की 250 लाइनें)

यहाँ अपने लेख से लेखक की झाँकी है, एक ऐसी दुनिया की कल्पना कीजिए जहाँ बैश JSON का समर्थन करता है :

#!/bin/bash
. ticktick.sh

``  
  people = { 
    "Writers": [
      "Rod Serling",
      "Charles Beaumont",
      "Richard Matheson"
    ],  
    "Cast": {
      "Rod Serling": { "Episodes": 156 },
      "Martin Landau": { "Episodes": 2 },
      "William Shatner": { "Episodes": 2 } 
    }   
  }   
``  

function printDirectors() {
  echo "  The ``people.Directors.length()`` Directors are:"

  for director in ``people.Directors.items()``; do
    printf "    - %s\n" ${!director}
  done
}   

`` people.Directors = [ "John Brahm", "Douglas Heyes" ] ``
printDirectors

newDirector="Lamont Johnson"
`` people.Directors.push($newDirector) ``
printDirectors

echo "Shifted: "``people.Directors.shift()``
printDirectors

echo "Popped: "``people.Directors.pop()``
printDirectors

2
यहाँ पर एकमात्र मजबूत शुद्ध-बाश उत्तर के रूप में, यह अधिक उत्थान के योग्य है।
एड रान्डल

क्या इस तरह के लोगों को फिर से एक जन्स स्ट्रिंग में बदलने का कोई तरीका है? यह बेहद उपयोगी होगा
थॉमस फोरनेट

अंत में पायथन या अन्य नृशंस तरीकों की सिफारिश नहीं करने का जवाब ... धन्यवाद!
Akito

21

PHP CLI के साथ पार्सिंग JSON

तर्कपूर्ण विषय लेकिन जब से पूर्ववर्ती शासनकाल से यह प्रश्न हमारे भरोसेमंद और वफादार PHP के उल्लेख के बिना अधूरा रहता है, क्या मैं सही हूं?

एक ही उदाहरण JSON का उपयोग करना, लेकिन यह अस्पष्टता को कम करने के लिए एक चर को असाइन करने देता है।

$ export JSON='{"hostname":"test","domainname":"example.com"}'

अब PHP अच्छाई के लिए, file_get_contents और php: // stdin स्ट्रीम आवरण का उपयोग करके ।

$ echo $JSON|php -r 'echo json_decode(file_get_contents("php://stdin"))->hostname;'

या जैसा कि फिट्स और पहले से ही खोले स्ट्रीम का उपयोग करके सीएलआई स्थिर STDIN में बताया गया है

$ echo $JSON|php -r 'echo json_decode(fgets(STDIN))->hostname;'

एन ज्वॉय!


तुम भी के $argnबजाय का उपयोग कर सकते हैंfgets(STDIN)
IcanDivideBy0

ओह, $argn-E या -R फ्लैग के साथ काम करता है और केवल तभी जब JSON कंटेंट एक लाइन पर हो ...
IcanDivideBy0

21

देशी बैश संस्करण: भी बैकस्लैश (\) और उद्धरण (") के साथ अच्छी तरह से काम करता है

function parse_json()
{
    echo $1 | \
    sed -e 's/[{}]/''/g' | \
    sed -e 's/", "/'\",\"'/g' | \
    sed -e 's/" ,"/'\",\"'/g' | \
    sed -e 's/" , "/'\",\"'/g' | \
    sed -e 's/","/'\"---SEPERATOR---\"'/g' | \
    awk -F=':' -v RS='---SEPERATOR---' "\$1~/\"$2\"/ {print}" | \
    sed -e "s/\"$2\"://" | \
    tr -d "\n\t" | \
    sed -e 's/\\"/"/g' | \
    sed -e 's/\\\\/\\/g' | \
    sed -e 's/^[ \t]*//g' | \
    sed -e 's/^"//'  -e 's/"$//'
}


parse_json '{"username":"john, doe","email":"john@doe.com"}' username
parse_json '{"username":"john doe","email":"john@doe.com"}' email

--- outputs ---

john, doe
johh@doe.com

यह कमाल का है। लेकिन अगर JSON स्ट्रिंग में एक से अधिक ईमेल कुंजी हैं, तो पार्सर john@doe.com "" john@doe.com
rtc11

अगर jean-pierre@email.com जैसे ईमेल में पानी का छींटा नहीं है तो काम नहीं करता
alexmngn

13

संस्करण जो रूबी और http://flori.github.com/json/ का उपयोग करता है

$ < file.json ruby -e "require 'rubygems'; require 'json'; puts JSON.pretty_generate(JSON[STDIN.read]);"

या अधिक संक्षेप में:

$ < file.json ruby -r rubygems -r json -e "puts JSON.pretty_generate(JSON[STDIN.read]);"

3
यह मेरा पसंदीदा है;) BTW आपको लाइब्रेरी की आवश्यकता के लिए रूबी -rjson के साथ इसे छोटा कर सकते हैं
ल्यूकपेट

ध्यान दें कि ;रूबी में फाइनल की आवश्यकता नहीं है (यह केवल संक्षिप्त विवरणों के लिए उपयोग किया जाता है जो सामान्य रूप से एक पंक्ति में अलग-अलग लाइनों पर होंगे)।
ज़ैक मॉरिस

11

दुर्भाग्य से शीर्ष मतदान का जवाब जो पूर्ण मिलान का उपयोग करता grepहै जो मेरे परिदृश्य में काम नहीं करता है, लेकिन अगर आपको पता है कि JSON प्रारूप स्थिर रहेगा तो आप केवल वांछित मानों को निकालने के लिए lookbehind और lookahead का उपयोग कर सकते हैं ।

# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="FooBar":")(.*?)(?=",)'
he\"llo
# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="TotalPages":)(.*?)(?=,)'
33
#  echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="anotherValue":)(.*?)(?=})'
100

आप वास्तव में JSON शब्दकोश में तत्वों के क्रम को कभी नहीं जानते हैं । वे परिभाषा से, अनियंत्रित हैं। यह मूल कारणों में से एक है कि अपने JSON पार्सर को रोल करना एक प्रचलित दृष्टिकोण क्यों है।
ट्रिपल

10

यदि कोई केवल नेस्टेड संरचनाओं की आवश्यकता के बिना सरल JSON ऑब्जेक्ट्स से मान निकालना चाहता है, तो बैश को छोड़कर भी नियमित अभिव्यक्ति का उपयोग करना संभव है।

यहाँ एक फ़ंक्शन है जिसे मैंने JSON मानक के आधार पर बैश नियमित अभिव्यक्तियों का उपयोग करके परिभाषित किया है :

function json_extract() {
  local key=$1
  local json=$2

  local string_regex='"([^"\]|\\.)*"'
  local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?'
  local value_regex="${string_regex}|${number_regex}|true|false|null"
  local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})"

  if [[ ${json} =~ ${pair_regex} ]]; then
    echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}")
  else
    return 1
  fi
}

कैविट्स: वस्तुओं और सरणियों को मूल्य के रूप में समर्थित नहीं किया जाता है, लेकिन मानक में परिभाषित सभी अन्य प्रकार समर्थित हैं। इसके अलावा, एक जोड़ी से कोई फर्क नहीं पड़ता कि JSON दस्तावेज़ में कितना गहरा है, जब तक कि यह वास्तव में एक ही कुंजी नाम नहीं है।

ओपी के उदाहरण का उपयोग करना:

$ json_extract text "$(curl 'http://twitter.com/users/username.json')"
My status

$ json_extract friends_count "$(curl 'http://twitter.com/users/username.json')"
245

हेलर परेरा क्या हम इस फ़ंक्शन के साथ नेस्टेड संपत्ति मान निकाल सकते हैं?
vsbehere

8

Json string से संपत्ति प्राप्त करने का एक आसान तरीका है। package.jsonएक उदाहरण के रूप में एक फ़ाइल का उपयोग करना , यह प्रयास करें:

#!/usr/bin/env bash
my_val="$(json=$(<package.json) node -pe "JSON.parse(process.env.json)['version']")"

हम उपयोग कर रहे हैं process.envक्योंकि इससे फ़ाइल की सामग्री नोड में आती है। किसी भी प्रकार की दुर्भावनापूर्ण सामग्री के बिना स्ट्रिंग के रूप में उनके उद्धरण से बचने और कोड के रूप में पार्स किया जाता है।


मानों को स्ट्रिंग समवर्ती में उपयोग करके स्ट्रिंग में पार्स किए गए मानों को कोड के रूप में मनमाने ढंग से नोड.जेएस कोड को चलाने की अनुमति देता है, जिसका अर्थ है कि इंटरनेट बंद होने पर यादृच्छिक सामग्री के साथ इसका उपयोग करना असुरक्षित है। जावास्क्रिप्ट में JSON को पार्स करने के लिए एक कारण सुरक्षित / सर्वोत्तम-अभ्यास तरीके हैं, बस इसका मूल्यांकन न करें।
चार्ल्स डफी

@CharlesDuffy सुनिश्चित नहीं है कि मैं अनुसरण करता हूं, लेकिन JSON.parse कॉल सुरक्षित होना चाहिए, क्योंकि require()वास्तव में विदेशी कोड चला सकता है, JSON.parse नहीं कर सकता।
अलेक्जेंडर मिल्स

यह सच है कि अगर और केवल-अगर आपकी स्ट्रिंग वास्तव में JSON रनटाइम में इस तरह से इंजेक्ट की जाती है जैसे कि पार्सर को बायपास करना। मैं यहाँ कोड को मज़बूती से नहीं देख रहा हूँ। इसे एक पर्यावरण चर से खींचो और इसे पास करो JSON.parse()और हाँ, आप स्पष्ट रूप से सुरक्षित हैं ... लेकिन यहां, JSON रनटाइम को (विश्वसनीय) कोड के साथ इन-बैंड सामग्री प्राप्त हो रही है
चार्ल्स डफी

... इसी तरह, यदि आपके पास आपका कोड एक स्ट्रिंग के रूप में फाइल से JSON पढ़ा है और उस स्ट्रिंग को पास कर दिया है JSON.parse(), तो आप सुरक्षित हैं, लेकिन यहां भी ऐसा नहीं हो रहा है।
चार्ल्स डफी

1
... आह, हेक, तुरंत "कैसे" में जा सकता है। समस्या यह है कि आप शेल चर को प्रतिस्थापित कर रहे हैं, जिसे आप JSON.parse()कोड में पारित करने का इरादा रखते हैं । आप मान रहे हैं कि शाब्दिक बैकटिक्स डालने से सामग्री शाब्दिक रहेगी, लेकिन यह पूरी तरह से असुरक्षित धारणा है, क्योंकि शाब्दिक बैकटिक्स फ़ाइल सामग्री (और इस प्रकार चर) में मौजूद हो सकते हैं, और इस प्रकार उद्धरण को समाप्त कर सकते हैं और एक निर्विवाद संदर्भ दर्ज कर सकते हैं जहां मानों को कोड के रूप में निष्पादित किया जाता है।
चार्ल्स डफी

7

अब जब पॉवर्सशेल क्रॉस प्लेटफॉर्म है, तो मैंने सोचा कि मैं इसका रास्ता निकाल दूंगा, क्योंकि मुझे लगता है कि यह काफी सहज और बेहद सरल है।

curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json 

ConvertFrom-Json, JSON को Powershell कस्टम ऑब्जेक्ट में परिवर्तित करता है, जिससे आप आसानी से उस बिंदु से आगे के गुणों के साथ काम कर सकते हैं। यदि आप उदाहरण के लिए केवल 'आईडी' संपत्ति चाहते हैं, तो आप बस यही करेंगे:

curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json | select -ExpandProperty id

यदि आप पूरी बात को बैश के भीतर से आह्वान करना चाहते हैं, तो आपको इसे इस तरह से कॉल करना होगा:

powershell 'curl -s "https://api.github.com/users/lambda" | ConvertFrom-Json'

बेशक कर्ल के बिना ऐसा करने का एक शुद्ध पॉवर्स तरीका है, जो होगा:

Invoke-WebRequest 'https://api.github.com/users/lambda' | select -ExpandProperty Content | ConvertFrom-Json

अंत में, 'ConvertTo-Json' भी है जो JSON में एक कस्टम ऑब्जेक्ट को आसानी से परिवर्तित करता है। यहाँ एक उदाहरण है:

(New-Object PsObject -Property @{ Name = "Tester"; SomeList = @('one','two','three')}) | ConvertTo-Json

जो इस तरह अच्छा JSON का उत्पादन करेगा:

{
"Name":  "Tester",
"SomeList":  [
                 "one",
                 "two",
                 "three"
             ]

}

बेशक, यूनिक्स पर विंडोज शेल का उपयोग करना कुछ हद तक पवित्र है लेकिन पॉवरशेल कुछ चीजों में वास्तव में अच्छा है, और JSON और XML को पार्स करना उनमें से कुछ हैं। यह GitHub पृष्ठ क्रॉस प्लेटफॉर्म संस्करण https://github.com/PowerShell/PowerShell के लिए है


upvoted क्योंकि आप अपने उपकरणों को खोलने के लिए नई Microsoft रणनीति को बढ़ावा दे रहे हैं, और खुले स्रोत के विदेशी उपकरणों को शामिल कर रहे हैं। यह हमारी दुनिया के लिए अच्छी बात है।
एलेक्स

मैं PowerShell को नापसंद करता था, लेकिन मुझे JSON की हैंडलिंग को स्वीकार करना चाहिए क्योंकि ऑब्जेक्ट बहुत अच्छा है।
मार्टिनोथे

6

कोई व्यक्ति जिसके पास xml फाइलें भी हैं, वह मेरे Xidel को देखना चाहेगा । यह एक cli, निर्भरता-मुक्त JSONiq प्रोसेसर है। (यानी यह xml या json प्रोसेसिंग के लिए XQuery का भी समर्थन करता है)

प्रश्न में उदाहरण यह होगा:

 xidel -e 'json("http://twitter.com/users/username.json")("name")'

या मेरे स्वयं के साथ, गैर मानक विस्तार वाक्यविन्यास:

 xidel -e 'json("http://twitter.com/users/username.json").name'

1
या आजकल सरल: xidel -s https://api.github.com/users/lambda -e 'name'(या -e '$json/name', -e '($json).name')।
रीनो

6

मैं यहां किसी भी उत्तर का उपयोग नहीं कर सकता। कोई उपलब्ध jq, कोई शेल सरणियां, कोई घोषणा नहीं, कोई grep -P, कोई लुकअप और लुकहेड, कोई पायथन, कोई पर्ल, कोई रूबी, नहीं - नहीं भी बैश ... शेष उत्तर बस अच्छी तरह से काम नहीं करते हैं। जावास्क्रिप्ट परिचित लग रहा था, लेकिन टिन Nescaffe कहते हैं - तो यह एक नहीं जाना है, भी :) अगर मेरी सरल जरूरत के लिए भी उपलब्ध है - वे overkill और धीमी गति से होगा।

फिर भी, मेरे लिए अपने मॉडेम के जसन स्वरूपित उत्तर से कई चर प्राप्त करना बेहद महत्वपूर्ण है। मैं इसे एक तरह से अपने रूटर्स में बिजीबॉक्स के साथ नीचे छंटनी कर रहा हूं! अकेले awk का उपयोग करने में कोई समस्या नहीं: बस सीमांकक सेट करें और डेटा पढ़ें। एक एकल चर के लिए, यह सब है!

awk 'BEGIN { FS="\""; RS="," }; { if ($2 == "login") {print $4} }' test.json

याद रखें मेरे पास कोई सरणियाँ नहीं हैं? मुझे 11 चर के लिए अजीब पार्स किए गए डेटा के भीतर असाइन करना था जो मुझे शेल स्क्रिप्ट में चाहिए। मैंने जहां भी देखा, कहा जाता है कि यह एक असंभव मिशन था। इसके साथ कोई समस्या नहीं है।

मेरा समाधान सरल है। यह कोड होगा: 1) प्रश्न से पार्स .json फ़ाइल (वास्तव में, मैंने सबसे ऊपर के उत्तर से एक कार्यशील डेटा नमूना उधार लिया है) और उद्धृत डेटा बाहर निकालता हूं, 2) awk असाइन किए गए मुक्त नामित शेल के भीतर से शेल चर बनाते हैं चर नाम।

eval $( curl -s 'https://api.github.com/users/lambda' | 
awk ' BEGIN { FS="\""; RS="," };
{
    if ($2 == "login") { print "Login=\""$4"\"" }
    if ($2 == "name") { print "Name=\""$4"\"" }
    if ($2 == "updated_at") { print "Updated=\""$4"\"" }
}' )
echo "$Login, $Name, $Updated"

भीतर कोई समस्या नहीं है। मेरे उपयोग में, एक ही कमांड एक लंबी सिंगल लाइन आउटपुट को पार्स करता है। जैसा कि eval का उपयोग किया जाता है, यह समाधान केवल विश्वसनीय डेटा के लिए अनुकूल है। अयोग्य डेटा को पिक करने के लिए इसे अनुकूलित करना सरल है। बड़ी संख्या में वैरिएबल के लिए, सीमांत गति का लाभ प्राप्त किया जा सकता है यदि अन्य। सरणी का अभाव स्पष्ट रूप से इसका मतलब है: बिना किसी अतिरिक्त हलचल के कई रिकॉर्ड। लेकिन जहां सरणियाँ उपलब्ध हैं, इस समाधान को अपनाना एक सरल कार्य है।

@maikel sed उत्तर लगभग काम करता है (लेकिन मैं इस पर टिप्पणी नहीं कर सकता)। मेरे अच्छे स्वरूपित डेटा के लिए - यह काम करता है। यहां इस्तेमाल किए गए उदाहरण के साथ इतना नहीं है (लापता उद्धरण इसे फेंक देते हैं)। यह संशोधित करने के लिए जटिल और कठिन है। साथ ही, मुझे 11 चर निकालने के लिए 11 कॉल करना पसंद नहीं है। क्यों? मैंने 9 चर निकालने वाले 100 लूप निकाले: सेड फंक्शन ने 48.99 सेकेंड का समय लिया और मेरे सॉल्यूशन ने 0.91 सेकेंड लिया! निष्पक्ष नहीं? 9 चर: 0.51 बनाम 0.02 सेकंड का एक ही निष्कर्षण करना।


5

आप कुछ इस तरह की कोशिश कर सकते हैं -

curl -s 'http://twitter.com/users/jaypalsingh.json' | 
awk -F=":" -v RS="," '$1~/"text"/ {print}'

5

आप उपयोग कर सकते हैं jshon:

curl 'http://twitter.com/users/username.json' | jshon -e text

साइट कहती है: "दो बार जितना तेज़, 1/6 वीं मेमोरी" ... और फिर: "जेशोन पार्स, पढ़ता है और JSON बनाता है। इसे शेल के भीतर से जितना संभव हो उतना डिज़ाइन करने के लिए डिज़ाइन किया गया है और नाजुक एड्रॉक पार्सर से बनाया गया है। grep / sed / awk साथ ही हैवीवेट / पायथन से बने हेवीवेट वन-लाइन पार्सर। "
रोजर

यह बैश में JSON को पार्स करने के लिए अनुशंसित समाधान के रूप में सूचीबद्ध है
qodeninja

परिणाम के आसपास उद्धरणों से छुटकारा पाने का सबसे आसान तरीका क्या है?
gMale

4

यहाँ एक तरह से आप इसे जाग के साथ कर सकते हैं

curl -sL 'http://twitter.com/users/username.json' | awk -F"," -v k="text" '{
    gsub(/{|}/,"")
    for(i=1;i<=NF;i++){
        if ( $i ~ k ){
            print $i
        }
    }
}'

4

अधिक जटिल JSON पार्सिंग के लिए, मैं पायथन जोंसपैथ मॉड्यूल (स्टीफन गेसनर द्वारा) का उपयोग करने का सुझाव देता हूं।

  1. इसे स्थापित करो -

sudo easy_install -U jsonpath

  1. इसका इस्तेमाल करें -

उदाहरण file.json ( http://goessner.net/articles/JsonPath से ) -

{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

इसे पार्स करें (मूल्य के साथ सभी पुस्तक के शीर्षक निकालें <10) -

$ cat file.json | python -c "import sys, json, jsonpath; print '\n'.join(jsonpath.jsonpath(json.load(sys.stdin), 'store.book[?(@.price < 10)].title'))"

उत्पादन होगा -

Sayings of the Century
Moby Dick

नोट: उपरोक्त कमांड लाइन में त्रुटि जाँच शामिल नहीं है। पूर्ण जाँच के साथ त्रुटि की जाँच के लिए आपको छोटे अजगर लिपि का निर्माण करना चाहिए, और कोड को कोशिश के अलावा लपेटना चाहिए।


सुंदर मुहावरा मैं अजगर भी नहीं जानता, लेकिन यह एक शक्तिशाली समाधान की तरह लगता है
श्रीधर सरनोबत

मुझे इसके बजाय jsonpathस्थापित करने में थोड़ी परेशानी हो रही थी jsonpath_rw, इसलिए यहां कुछ ऐसा ही है जिसे आप आजमा सकते हैं यदि ऊपर काम नहीं करता है: 1) /usr/bin/python -m pip install jsonpath-rw2) cat ~/trash/file.json | /usr/bin/python -c "from jsonpath_rw import jsonpath, parse; import sys,json; jsonpath_expr = parse('store.book[0]'); out = [match.value for match in jsonpath_expr.find(json.load(sys.stdin))]; print out;"(मैंने अजगर को बाइनरी करने के लिए पूर्ण पथ का उपयोग किया क्योंकि मुझे कई अजगर के साथ कुछ समस्याएँ थीं स्थापित)।
श्रीधर सरनोबत

4

यदि आपके पास php है :

php -r 'var_export(json_decode(`curl http://twitter.com/users/username.json`, 1));'

उदाहरण के लिए:
हमारे पास ऐसे संसाधन हैं जो देशों को आईएसओ कोड प्रदान करते हैं: http://country.io/iso3.json और हम इसे आसानी से कर्ल के साथ एक खोल में देख सकते हैं:

curl http://country.io/iso3.json

लेकिन यह बहुत सुविधाजनक नहीं है, और पठनीय, बेहतर पार्स जोंस और पठनीय संरचना नहीं देखता है:

php -r 'var_export(json_decode(`curl http://country.io/iso3.json`, 1));'

यह कोड कुछ इस तरह छपेगा:

array (
  'BD' => 'BGD',
  'BE' => 'BEL',
  'BF' => 'BFA',
  'BG' => 'BGR',
  'BA' => 'BIH',
  'BB' => 'BRB',
  'WF' => 'WLF',
  'BL' => 'BLM',
  ...

यदि आपके पास नेस्टेड एरेज़ है तो यह आउटपुट बहुत बेहतर लगेगा ...

आशा है कि यह उपयोगी होगा ...


4

एक बहुत ही सरल लेकिन शक्तिशाली JSON CLI प्रोसेसिंग टूल fx - https://github.com/antonmedv/fx भी है

बैश टर्मिनल में JSON फॉर्मेटिंग का उदाहरण

उदाहरण

अनाम फ़ंक्शन का उपयोग करें:

$ echo '{"key": "value"}' | fx "x => x.key"
value

यदि आप अनाम फ़ंक्शन को पास नहीं करते हैं तो>> ..., कोड स्वचालित रूप से अनाम फ़ंक्शन में बदल जाएगा। और आप इस कीवर्ड द्वारा JSON तक पहुँच प्राप्त कर सकते हैं:

$ echo '[1,2,3]' | fx "this.map(x => x * 2)"
[2, 4, 6]

या बस डॉट सिंटैक्स का भी उपयोग करें:

$ echo '{"items": {"one": 1}}' | fx .items.one
1

JSON को कम करने के लिए आप कितने भी अनाम कार्य कर सकते हैं:

$ echo '{"items": ["one", "two"]}' | fx "this.items" "this[1]"
two

आप मौजूदा ऑपरेटर का उपयोग करके मौजूदा JSON को अपडेट कर सकते हैं:

$ echo '{"count": 0}' | fx "{...this, count: 1}"
{"count": 1}

बस सादा जावास्क्रिप्ट । नया वाक्यविन्यास सीखने की जरूरत नहीं है।


UPDATE 2018-11-06

fxअब इंटरैक्टिव मोड है ( ! )

https://github.com/antonmedv/fx


7
यदि आप अपनी खुद की रचना को बढ़ावा दे रहे हैं, तो आपको इसके बारे में स्पष्ट होना चाहिए। देखें कि कैसे एक स्पैमर नहीं है।
ट्रिपल

4

यह अभी तक एक bashऔर pythonहाइब्रिड उत्तर है। मैंने यह उत्तर इसलिए पोस्ट किया क्योंकि मैं JSON आउटपुट को और अधिक जटिल बनाना चाहता था, लेकिन, अपने बैश एप्लिकेशन की जटिलता को कम कर रहा था। मैं से निम्नलिखित JSON ऑब्जेक्ट खुला दरार करना चाहते http://www.arcgis.com/sharing/rest/info?f=json में bash:

{
  "owningSystemUrl": "http://www.arcgis.com",
  "authInfo": {
    "tokenServicesUrl": "https://www.arcgis.com/sharing/rest/generateToken",
    "isTokenBasedSecurity": true
  }
}

निम्नलिखित उदाहरण में, मैंने अपना स्वयं का कार्यान्वयन jqऔर unquoteलाभ उठाया python। आप ध्यान दें कि एक बार जब हम jsonएक अजगर शब्दकोष से अजगर वस्तु को आयात करते हैं तो हम शब्दकोश को नेविगेट करने के लिए अजगर वाक्यविन्यास का उपयोग कर सकते हैं। उपरोक्त नेविगेट करने के लिए, वाक्यविन्यास है:

  • data
  • data[ "authInfo" ]
  • data[ "authInfo" ][ "tokenServicesUrl" ]

बैश में जादू का उपयोग करके, हम dataडेटा के दाईं ओर केवल अजगर पाठ को छोड़ते हैं और आपूर्ति करते हैं, अर्थात

  • jq
  • jq '[ "authInfo" ]'
  • jq '[ "authInfo" ][ "tokenServicesUrl" ]'

ध्यान दें, कोई मापदंडों के साथ, jq JSON प्रीटीफायर के रूप में कार्य करता है। मापदंडों के साथ हम अजगर से कुछ भी निकालने के लिए शब्दकोष का उपयोग कर सकते हैं, जिसमें उप-शब्दकोश और सरणी तत्वों को शामिल करना चाहते हैं।

यहाँ एक कार्यशील उदाहरण दिया गया है जो उपरोक्त प्रदर्शित करता है:

jq_py() {
cat <<EOF
import json, sys
data = json.load( sys.stdin )
print( json.dumps( data$1, indent = 4 ) )
EOF
}

jq() {
  python -c "$( jq_py "$1" )"
}

unquote_py() {
cat <<EOF
import json,sys
print( json.load( sys.stdin ) )
EOF
}

unquote() {
  python -c "$( unquote_py )"
}

curl http://www.arcgis.com/sharing/rest/info?f=json | tee arcgis.json
# {"owningSystemUrl":"https://www.arcgis.com","authInfo":{"tokenServicesUrl":"https://www.arcgis.com/sharing/rest/generateToken","isTokenBasedSecurity":true}}

cat arcgis.json | jq
# {
#     "owningSystemUrl": "https://www.arcgis.com",
#     "authInfo": {
#         "tokenServicesUrl": "https://www.arcgis.com/sharing/rest/generateToken",
#         "isTokenBasedSecurity": true
#     }
# }

cat arcgis.json | jq '[ "authInfo" ]'
# {
#     "tokenServicesUrl": "https://www.arcgis.com/sharing/rest/generateToken",
#     "isTokenBasedSecurity": true
# }

cat arcgis.json | jq '[ "authInfo" ][ "tokenServicesUrl" ]'
# "https://www.arcgis.com/sharing/rest/generateToken"

cat arcgis.json | jq '[ "authInfo" ][ "tokenServicesUrl" ]' | unquote
# https://www.arcgis.com/sharing/rest/generateToken

3

मैंने यह किया है, एक विशेष मूल्य के लिए एक json प्रतिक्रिया "पार्सिंग", इस प्रकार है:

curl $url | grep $var | awk '{print $2}' | sed s/\"//g 

जाहिर है, यहां $ url ट्विटर url होगा, और उस var के लिए प्रतिसाद प्राप्त करने के लिए $ var "पाठ" होगा।

वास्तव में, मुझे लगता है कि केवल एक चीज जो मैं कर रहा हूं ओपी ने छोड़ दिया है वह उस विशिष्ट चर के साथ grep है जो वह चाहता है। Awk लाइन पर दूसरा आइटम पकड़ता है, और sed के साथ मैं उद्धरणों को छीनता हूं।

किसी के होशियार होने से शायद मैं पूरी सोच के साथ जाग या जीआरपी के साथ कर सकता हूं।

अब, आप यह सब सिर्फ sed के साथ कर सकते हैं:

curl $url | sed '/text/!d' | sed s/\"text\"://g | sed s/\"//g | sed s/\ //g

इस प्रकार, कोई awk, कोई grep नहीं ... मुझे नहीं पता कि मैंने इसके बारे में पहले क्यों नहीं सोचा। हममम ...


दरअसल, sed के साथ आप कर सकते हैं
tonybaldwin

1
grep | awk | sedऔर sed | sed | sedपाइपलाइनों बेकार antipatterns हैं। आपके अंतिम उदाहरण को आसानी से फिर से लिखा जा सकता है, curl "$url" | sed '/text/!d;s/\"text\"://g;s/\"//g;s/\ //g'लेकिन जैसा कि दूसरों ने बताया है, यह त्रुटि और प्रवणता और भंगुर दृष्टिकोण है जिसे पहले स्थान पर अनुशंसित नहीं किया जाना चाहिए।
ट्रिपलए

मुझे grep -oPz 'name \ ": \"। * का उपयोग करना था। \ "' curloutput | sed 's / name \": / \ n / g'
फेरो

3

PSONing JSON शेल स्क्रिप्ट में दर्दनाक है। अधिक उपयुक्त भाषा के साथ, एक उपकरण बनाएं जो शेल स्क्रिप्टिंग सम्मेलनों के अनुरूप JSON विशेषताओं को निकालता है। आप तत्काल शेल स्क्रिप्टिंग समस्या को हल करने के लिए अपने नए टूल का उपयोग कर सकते हैं और फिर भविष्य की स्थितियों के लिए इसे अपनी किट में जोड़ सकते हैं।

उदाहरण के लिए, एक उपकरण jsonlookup पर विचार करें जैसे कि अगर मैं कहता हूं कि jsonlookup access token idयह स्टड से विशेषता एक्सेस के भीतर परिभाषित विशेषता टोकन के भीतर परिभाषित विशेषता आईडी लौटाएगा , जो संभवतः JSON डेटा है। यदि विशेषता मौजूद नहीं है, तो टूल कुछ भी नहीं देता है (निकास स्थिति 1)। यदि पार्सिंग विफल हो जाता है, तो स्थिति 2 से बाहर निकलें और स्टेडर को संदेश। यदि लुकअप सफल होता है, तो टूल विशेषता के मान को प्रिंट करता है।

JSON मूल्यों को निकालने के सटीक उद्देश्य के लिए एक यूनिक्स टूल बनाया है जिसे आप शेल स्क्रिप्ट में आसानी से उपयोग कर सकते हैं:

access_token=$(curl <some horrible crap> | jsonlookup access token id)

कोई भी भाषा jsonlookup के कार्यान्वयन के लिए करेगी । यहाँ एक काफी संक्षिप्त अजगर संस्करण है:

#!/usr/bin/python                                                               

import sys
import json

try: rep = json.loads(sys.stdin.read())
except:
    sys.stderr.write(sys.argv[0] + ": unable to parse JSON from stdin\n")
    sys.exit(2)
for key in sys.argv[1:]:
    if key not in rep:
        sys.exit(1)
    rep = rep[key]
print rep

3

एक दो-लाइनर जो अजगर का उपयोग करता है। यह विशेष रूप से अच्छी तरह से काम करता है यदि आप एक .sh फ़ाइल लिख रहे हैं और आप किसी अन्य .py फ़ाइल पर निर्भर नहीं होना चाहते हैं। यह पाइप के उपयोग का भी लाभ उठाता है |echo "{\"field\": \"value\"}"किसी भी चीज़ को प्रिंट करने के लिए एक json द्वारा प्रतिस्थापित किया जा सकता है।

echo "{\"field\": \"value\"}" | python -c 'import sys, json
print(json.load(sys.stdin)["field"])'

सवाल पायथन समाधान की तलाश में नहीं था। टिप्पणियों को भी देखें।
एंड्रयू बार्बर

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