ट्रैक
/
jq
jq
/
सिलेबस
/
मूल बातें
मू

मूल बातें में jq

1 अभ्यास

मूल बातें के बारे में

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

jq के कमांड-लाइन विकल्पों का छोटा परिचय

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 विकल्प इस्तेमाल करते हैं। प्रैक्टिस अभ्यासों की टेस्ट स्क्रिप्ट में आपको यह इस्तेमाल होते दिखेगा।

सभी विकल्पों की जानकारी के लिए मैनुअल देखिए।

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

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

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

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

यह सबसे आसान फिल्टर है। यह अपना इनपुट ज्यों का त्यों आउटपुट पर भेज देता है। जैसे, jq डिफ़ॉल्ट रूप से आउटपुट सजाकर छापता है, तो JSON को . फिल्टर से गुज़ारने पर अच्छी तरह सजा हुआ आउटपुट बिना किसी मेहनत के मिल जाता है!

$ 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"

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

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

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

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

का आउटपुट है

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

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

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

बड़े ऑब्जेक्ट से कुछ चुनिंदा की निकालना काफी आम ज़रूरत है। जैसे, इसमें से id और name निकालने के लिए

{
    "id": 101,
    "name": "alpha widget",
    "specifications": {...}
}

हम ऐसे लिख सकते हैं

{id: .id, name: .name}

लेकिन यह इतना आम है कि इसके लिए छोटा सिंटैक्स भी मौजूद है:

{id, name}

पाइपलाइन

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

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

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

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

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

Caution

jq की यह बात समझने में थोड़ा समय लगता है। ज़्यादातर फंक्शन (लेकिन सारे नहीं) फिल्टरों की तरह काम करते हैं, जहाँ आप डेटा फिल्टर के इनपुट में देते हैं, आर्गुमेंट की तरह नहीं।

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

इस उदाहरण में, इनपुट 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 का वर्गमूल, और e की घात 1। दोनों अलग-अलग एक्सप्रेशन हैं: 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
]

टाइप

मैनुअल से

jq, JSON जितने ही डेटा टाइप सपोर्ट करता है, यानी संख्याएँ, स्ट्रिंग, बूलियन, ऐरे, ऑब्जेक्ट (जिन्हें JSON की भाषा में हैश कहते हैं, जिनकी की सिर्फ स्ट्रिंग होती हैं), और "null"।

इनके बारे में आप आगे के अभ्यासों में और सीखेंगे।

खाली जगह

jq में खाली जगह का कोई महत्व नहीं है। अपने कोड को सजाने के लिए स्पेस, टैब और नई लाइन जैसे चाहें वैसे इस्तेमाल कीजिए। हमें jq के लिए कोई मौजूदा स्टाइल गाइड नहीं मालूम।

अपरिवर्तनीय वैल्यू

jq में वैल्यू अपरिवर्तनीय होती हैं। जो फिल्टर किसी वैल्यू को बदलते हैं, वे नई वैल्यू देते हैं। इसका मतलब है कि jq में ग्लोबल वेरिएबल नहीं होते। आपको एक फिल्टर से दूसरे फिल्टर तक स्थिति पहुँचाने की आदत डालनी होगी।

"सत्यता"

false और null वैल्यू को गलत माना जाता है। बाकी हर वैल्यू (शून्य संख्या, और खाली स्ट्रिंग/ऐरे/ऑब्जेक्ट सहित) सही मानी जाती है।

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

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

  • 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) ]
      

टिप्पणियाँ

टिप्पणियाँ # अक्षर से शुरू होती हैं और लाइन के अंत तक चलती हैं।

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

मूल बातें सीखिए