ट्रैक
/
jq
jq
/
अभ्यास
/
खरीदारी की सूची
खरीदारी की सूची

खरीदारी की सूची

सीखने का अभ्यास

परिचय

मूल बातें

हम मान लेते हैं कि आप JSON सिंटैक्स और डेटा टाइप से परिचित हैं।

jq आने वाले JSON डेटा को एक एक्सप्रेशन (जिसे फिल्टर की पाइपलाइन के रूप में लिखा जाता है) से गुज़ारकर मनचाहा रूपांतरित डेटा हासिल करता है।

Note

jq भाषा को jq प्रोग्राम लागू करता है। यह प्रोग्राम कई उपयोगी कमांड-लाइन ऑप्शन देता है, जिनसे आप नियंत्रित कर सकते हैं कि इनपुट कैसे पढ़ा जाए और आउटपुट कैसे दिखाया जाए।

नीचे के उदाहरणों में आपको ये मिलेंगे:

  • -n या --null-input

    सामान्य रूप से jq प्रोग्राम को पढ़ने के लिए एक फाइल दी जाती है, या आप उसके इनपुट पर डेटा भेजते हैं। --null-input ऑप्शन आपको बिना किसी इनपुट के JSON डेटा बनाने देता है।

  • -c या --compact-output

    jq डिफ़ॉल्ट रूप से अपना आउटपुट सुंदर ढंग से छापता है। डेटा अच्छी तरह फॉर्मेट किया हो तो इंसानों के लिए उसे देखना बहुत उपयोगी रहता है। पर मशीनों के लिए यह ज़रूरी नहीं है: --compact-output ऑप्शन फॉर्मेटिंग की खाली जगह हटाकर बनने वाले JSON का आकार छोटा कर देता है।

  • -f filename या --from-file filename

    jq प्रोग्राम को कमांड लाइन पर देने के बजाय filename से पढ़िए। sed और awk दोनों इसी काम के लिए -f ऑप्शन इस्तेमाल करते हैं। आप इसे अभ्यासों की टेस्ट स्क्रिप्ट में इस्तेमाल होते देखेंगे।

इस पाठ का बाकी हिस्सा jq भाषा पर केंद्रित रहेगा।

फिल्टर और पाइप

फिल्टर को एक्सप्रेशन भी कहा जाता है।

एक फिल्टर एक इनपुट लेता है और एक आउटपुट बनाता है। जैसे आप Unix शेल में काम करते हैं, वैसे ही आप पाइप | से फिल्टर जोड़ सकते हैं, जिससे एक फिल्टर का आउटपुट दूसरे के इनपुट से जुड़ जाता है।

आइडेंटिटी फिल्टर: .

यह सबसे आसान फिल्टर है। यह अपने इनपुट को बस आउटपुट तक पहुँचा देता है।

$ echo '[1, 2, 3]' | jq '.'
[
  1,
  2,
  3
]

ऐरे

यह ऐरे के साथ काम करने का एक छोटा परिचय रहेगा। इस विषय पर हम बाद में और विस्तार से बात करेंगे।

ऐरे के एलिमेंट तक ब्रैकेट से पहुँचा जाता है, और उनकी गिनती शून्य से शुरू होती है।

$ echo '[10, 20, 30]' | jq '.[1]'
20

एक फिल्टर किसी एक्सप्रेशन को [ और ] में लपेटकर एक ऐरे बना सकता है:

  • एलिमेंट की ज्ञात सूची के साथ:

    jq -n '[1, 2, 3]'
    
  • एलिमेंट की स्ट्रीम जमा करने के लिए: जैसे, range एक फंक्शन है जो संख्याओं की स्ट्रीम आउटपुट करता है

    $ jq -n 'range(10; 70; 15)'
    10
    25
    40
    55
    

    [] इस्तेमाल करने पर एक्सप्रेशन के नतीजे एक ऐरे में जमा हो जाते हैं

    $ jq -c -n '[range(10; 70; 15)]'
    [10,25,40,55]
    

कॉमा एक ऑपरेटर है

कॉमा सिर्फ वह सिंटैक्स नहीं है जो ऐरे के एलिमेंट अलग करता है। कॉमा एक ऑपरेटर है जो स्ट्रीम जोड़ता है।

जैसे [1, 2, 3] एक फिल्टर है जो ऐरे कंस्ट्रक्टर [] का इस्तेमाल करके तीन एक्सप्रेशन 1, 2 और 3 को जोड़ने का नतीजा जमा करता है।

क्या आपने ऊपर range(10; 70; 15) में सेमीकोलन देखे? चूँकि jq भाषा में कॉमा का एक खास उद्देश्य है, इसलिए कई आर्गुमेंट लेने वाले फंक्शन आर्गुमेंट अलग करने के लिए सेमीकोलन इस्तेमाल करते हैं।

ऑब्जेक्ट

ऑब्जेक्ट के साथ काम करने का एक छोटा परिचय।

कई प्रोग्रामिंग भाषाओं की तरह, ऑब्जेक्ट की प्रॉपर्टी तक पहुँचने के लिए डॉट इस्तेमाल कीजिए

$ echo '{"foo": {"bar": "qux"}}' | jq '.foo.bar'
"qux"
Note

ऑब्जेक्ट के लिए ब्रैकेट भी इस्तेमाल किए जा सकते हैं, पर तब स्ट्रिंग लिटरल के लिए कोटेशन चाहिए। यह उन कीज़ के साथ काम करने का एक तरीका है जिनमें स्पेस होते हैं।

$ echo '{"foo bar": "qux"}' | jq '.["foo bar"]'
"qux"

आप {} और key: value जोड़ों से एक ऑब्जेक्ट बना सकते हैं। जो की "सामान्य" स्ट्रिंग होती हैं, उनके आसपास कोटेशन ज़रूरी नहीं होते।

jq -n '{question: (6 * 9), answer: 42}'

आउटपुट देता है

{
  "question": 54,
  "answer": 42
}

की को एक्सप्रेशन की तरह इस्तेमाल करने के लिए आपको उसे गोल ब्रैकेटों में लपेटना होगा (नीचे वाला भी ऊपर जैसा ही आउटपुट देता है)।

echo '[{"key":"question", "value":54}, {"key":"answer", "value":42}]' \
| jq '{(.[0].key): .[0].value, (.[1].key): .[1].value}'

पाइपलाइन

जैसे, मान लीजिए file.json में यह है

{
  "key1": "value1",
  "key2": [5, 15, 25]
}

आइए key2 ऐरे की लंबाई निकालते हैं:

$ jq '.key2 | length' file.json
3

हम .key2 एक्सप्रेशन के आउटपुट को length के इनपुट की तरह पाइप कर रहे हैं, जो स्वाभाविक रूप से ऐरे में मौजूद एलिमेंट की संख्या आउटपुट करता है।

फिल्टर अपने इनपुट को अनदेखा कर सकते हैं

इस उदाहरण में इनपुट JSON डेटा अनदेखा किया जाता है और उसका आउटपुट पर कोई असर नहीं पड़ता:

$ echo '{"answer": 42}' | jq '6 * 9'
54

फिल्टर डेटा की स्ट्रीम आउटपुट कर सकते हैं

एक फिल्टर एक से अधिक वैल्यू आउटपुट कर सकता है। जैसे, .[] फिल्टर ऐरे के हर एलिमेंट को एक अलग वैल्यू की तरह आउटपुट करता है:

$ jq -n -c '[1, 2, 3]'
[1,2,3]

$ jq -n -c '[1, 2, 3] | .[]'
1
2
3

ऐसे फिल्टर को किसी दूसरे में पाइप करने पर दूसरा फिल्टर हर वैल्यू के लिए चलता है:

$ jq -n -c '[1, 2, 3] | .[] | . * 2'
2
4
6

यह अंतर्निहित इटरेशन जैसा है। एक बार यह तकनीक समझ लेने पर आप देखेंगे कि बहुत शक्तिशाली jq फिल्टर बहुत संक्षिप्त हो सकते हैं।

गोल ब्रैकेट

गोल ब्रैकेट उप-एक्सप्रेशनों को एक साथ समूहित करने के लिए इस्तेमाल किए जाते हैं ताकि संक्रियाओं का क्रम तय हो, बिल्कुल दूसरी भाषाओं की तरह। jq में इनकी ज़रूरत कभी-कभी कुछ चौंकाने वाली लग सकती है।

जैसे, मान लीजिए हम 2 एलिमेंट वाला एक ऐरे बनाना चाहते हैं: 9 का वर्गमूल, और 1 की घात तक उठाया गया e। दोनों अलग एक्सप्रेशन हैं 9 | sqrt और 1 | exp। हमें उम्मीद है कि आउटपुट ऐरे [3, 2.7...] होगा

$ jq -n '[ 9|sqrt, 1|exp ]'
[
  20.085536923187668,
  2.718281828459045
]

हमें वह क्यों नहीं मिला जिसकी उम्मीद थी? jq उसे ऐसे समझता है:

[ ((9|sqrt), 1) | exp ]

jq दो एलिमेंट (3 और 1) की एक स्ट्रीम बनाता है, और इन दोनों को exp को दिया जाता है।

हमें यह सुनिश्चित करना है कि exp इनपुट में सिर्फ एक संख्या ले। दूसरे शब्दों में, हमें यह तय करना है कि पाइप का मूल्यांकन कॉमा से पहले हो।

$ jq -n '[ 9|sqrt, (1|exp) ]'
[
  3,
  2.718281828459045
]

फंक्शन और ऑपरेटर

बहुत गहराई में जाए बिना (फंक्शन किसी और अभ्यास का विषय होंगे), यहाँ कुछ उपयोगी बिल्ट-इन फंक्शन दिए गए हैं:

  • length

    इनपुट में एक ऐरे लेकर उसमें मौजूद एलिमेंट की संख्या आउटपुट कीजिए।

    $ jq -n '[10, 20, 30, 40] | length'
    4
    
  • +

    यह ऑपरेटर अपने ऑपरेंड के टाइप के हिसाब से अलग-अलग काम करता है: यह संख्याएँ जोड़ता है, यह स्ट्रिंग जोड़ता है, यह ऐरे जोड़ता है, यह ऑब्जेक्ट मिलाता है।

    $ jq -c -n '
        3 + 4,
        "foo" + "bar",
        ["a", "b"] + ["c"],
        {"m": 10} + {"n": 20}
    '
    7
    "foobar"
    ["a","b","c"]
    {"m":10,"n":20}
    

    add एक फंक्शन है जो एक ऐरे लेता है और + के नियमों से सारे एलिमेंट जोड़कर बना एक आइटम लौटाता है। [1, 2, 3] | add आउटपुट देता है 6।

  • map

    इनपुट में एक ऐरे और आर्गुमेंट के तौर पर एक फिल्टर लेकर एक ऐसा ऐरे आउटपुट कीजिए जिसमें हर एलिमेंट पर वह फिल्टर लागू हो

    $ jq -c -n '[10, 20, 30, 40] | map(. / 5)'
    [2,4,6,8]
    
  • select

    कुछ इनपुट और आर्गुमेंट के तौर पर एक फिल्टर लेकर:

    • अगर आर्गुमेंट पर लागू किए गए फिल्टर का नतीजा एक सही वैल्यू हो, तो इनपुट को जैसा है वैसा ही आउटपुट कीजिए
    • वरना कुछ भी नहीं आउटपुट कीजिए (null वैल्यू नहीं, बिल्कुल भी आउटपुट नहीं)

    जैसे, कुछ संख्याएँ दी गई हों, तो उनमें से 3 से विभाज्य संख्याएँ चुनिए

    $ jq -n 'range(10) | select(. % 3 == 0)'
    0
    3
    6
    9
    

    याद रखिए कि range संख्याओं की एक स्ट्रीम आउटपुट करता है। select हर संख्या के लिए एक बार चलाया जाता है। सिर्फ वे संख्याएँ आउटपुट होती हैं जो उस एक्सप्रेशन को "पास" करती हैं।

    आपको अक्सर ऐरे के एलिमेंट चुनने पड़ते हैं। यह करने के कुछ तरीके हैं।

    इनपुट ["Anne", "Bob", "Cathy", "Dave"] के साथ, वे नाम चुनिए जिनकी लंबाई 4 है।

    • map और select साथ में इस्तेमाल कीजिए

      map(select(length == 4))
      
    • ऐरे को एलिमेंट में खोलिए, उस स्ट्रीम पर select कीजिए, और नतीजे जमा कीजिए

      [ .[] | select(length == 4) ]
      

कमेंट

कमेंट # अक्षर से शुरू होते हैं और लाइन के अंत तक चलते हैं।

निर्देश

आपको अचानक पैनकेक खाने का मन करता है। आप एक आधुनिक, तकनीक में रुचि रखने वाले इंसान हैं, इसलिए पैनकेक बनाने की सामग्री की शॉपिंग लिस्ट JSON फॉर्मैट में लिखते हैं। लिस्ट की संरचना इस तरह है:

{
  "name": "name of shopping list",
  "ingredients": [ ...list of ingredients... ],
  "optional ingredients": [ ...list of ingredients... ]
}

हर सामग्री को एक JSON ऑब्जेक्ट के रूप में लिखा जाता है, जैसे:

{
  "item": "flour",
  "amount": {
    "quantity": 2,
    "unit": "cup"
  }
}

हर सामग्री में एक वैकल्पिक प्रॉपर्टी हो सकती है जिसका नाम "substitute" है, और उसमें किसी दूसरी चीज़ का नाम स्ट्रिंग के रूप में रखा जाता है, जिसे उसकी जगह इस्तेमाल किया जा सकता है।

चलिए देखते हैं कि jq की मदद से शॉपिंग लिस्ट को कैसे जाँचा जा सकता है।

1. शॉपिंग लिस्ट का नाम निकालिए

एक एक्सप्रेशन लिखिए जो शॉपिंग लिस्ट का "name" एलिमेंट आउटपुट देता है।

2. गिनिए कि कितनी सामग्रियाँ चाहिए

सिर्फ़ ज़रूरी सामग्रियों को गिनिए। वैकल्पिक सामग्रियों को शामिल न कीजिए।

3. कितनी चीनी?

एक एक्सप्रेशन लिखिए जो चीनी की मात्रा आउटपुट देता है। सिर्फ़ संख्यात्मक हिस्सा चाहिए।

4. जिन सामग्रियों को बदला जा सकता है, उनकी मैपिंग बनाइए

कुछ सामग्रियों की जगह कोई और चीज़ इस्तेमाल की जा सकती है (अगर आपके पास सामग्री X नहीं है, तो आप Y इस्तेमाल कर सकते हैं)। एक JSON ऑब्जेक्ट आउटपुट दीजिए जो सुझाई गई सामग्री को उसके विकल्प से जोड़ता हो। मैपिंग में वैकल्पिक सामग्रियों को भी शामिल कीजिए।

GitHub के ज़रिए संपादित करें यह लिंक एक नई विंडो या टैब में खुलता है
jq Exercism

खरीदारी की सूची शुरू करने के लिए तैयार हैं?

Exercism पर साइन अप कीजिए और jq को 12 कॉन्सेप्ट75 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।