रेगुलर एक्सप्रेशन (रेगेक्स) अक्षरों के ऐसे क्रम होते हैं जो टेक्स्ट में खोजने का पैटर्न तय करते हैं।
रेगुलर एक्सप्रेशन का सिंटैक्स सीखना इस विषय के दायरे से बाहर है।
हम उन एक्सप्रेशनों पर ध्यान देंगे जो jq रेगेक्स इस्तेमाल करने के लिए उपलब्ध कराता है।
हर टूल रेगुलर एक्सप्रेशन का अपना संस्करण लागू करता है।
jq में Oniguruma रेगेक्स लाइब्रेरी शामिल है, जो ज़्यादातर Perl v5.8 के रेगेक्स से मेल खाती है।
jq जो खास सिंटैक्स इस्तेमाल करता है, वह Oniguruma के GitHub रेपो पर मिल सकता है।
jq में रेगुलर एक्सप्रेशन के लिए कोई खास सिंटैक्स नहीं है।
इन्हें सीधे स्ट्रिंग के रूप में लिखा जाता है।
इसका मतलब है कि रेगुलर एक्सप्रेशन में जो भी बैकस्लैश हों, उन्हें स्ट्रिंग में एस्केप करना पड़ता है।
जैसे, अंकों के लिए कैरेक्टर क्लास (\d) को "\\d" लिखना ज़रूरी है।
jq में रेगुलर एक्सप्रेशन कुछ फिल्टरों तक ही सीमित हैं।
जब आपको यह जानना हो कि कोई स्ट्रिंग किसी पैटर्न से मेल खाती है या नहीं, तो test फिल्टर का इस्तेमाल कीजिए।
STRING | test(REGEX)
STRING | test(REGEX; FLAGS)
STRING | test([REGEX, FLAGS])
यह फिल्टर एक बूलियन परिणाम देता है।
"Hello World!" | test("W") # => true
"Goodbye Mars" | test("W") # => false
जब आपको वह सबस्ट्रिंग निकालनी हो जो असल में पैटर्न से मेल खाई हो, तो match फिल्टर का इस्तेमाल कीजिए।
STRING | match(REGEX)
STRING | match(REGEX; FLAGS)
STRING | match([REGEX, FLAGS])
यह फिल्टर यह देता है:
यह उदाहरण बैकरेफ सिंटैक्स \1 से लगातार आने वाले दो एक जैसे स्वर ढूँढता है।
"Hello World!" | match("([aeiou])\\1")
# => empty
"Goodbye Mars" | match("([aeiou])\\1")
# => {
# "offset": 1,
# "length": 2,
# "string": "oo",
# "captures": [
# {
# "offset": 1,
# "length": 1,
# "string": "o",
# "name": null
# }
# ]
# }
match फिल्टर हर मिलान के लिए एक ऑब्जेक्ट लौटाता है।
यह उदाहरण सारे स्वर ढूँढने के लिए "g" फ्लैग को काम करते हुए दिखाता है।
"Goodbye Mars" | match("[aeiou]"; "g")
# => { "offset": 1, "length": 1, "string": "o", "captures": [] }
# { "offset": 2, "length": 1, "string": "o", "captures": [] }
# { "offset": 6, "length": 1, "string": "e", "captures": [] }
# { "offset": 9, "length": 1, "string": "a", "captures": [] }
match फिल्टर की तरह, capture फिल्टर भी मिलान होने पर एक ऑब्जेक्ट लौटाता है।
STRING | capture(REGEX)
STRING | capture(REGEX; FLAGS)
STRING | capture([REGEX, FLAGS])
जो ऑब्जेक्ट लौटता है, वह नेम्ड कैप्चर का मैप होता है।
"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")
# => {
# "project": "JIRAISSUE",
# "issue_num": "1234"
# }
scan फिल्टर "g" फ्लैग लगे match जैसा ही है।
STRING | scan(REGEX)
STRING | scan(REGEX; FLAGS)
scan सबस्ट्रिंग की एक स्ट्रीम देता है।
"Goodbye Mars" | scan("[aeiou]")
# => "o"
# "o"
# "e"
# "a"
सबस्ट्रिंग पकड़ने के लिए [...] ऐरे कंस्ट्रक्टर का इस्तेमाल कीजिए।
"Goodbye Mars" | [ scan("[aeiou]") ]
# => ["o", "o", "e", "a"]
अगर आपको पता है कि स्ट्रिंग के कौन-से हिस्से आप रखना चाहते हैं, तो match या scan का इस्तेमाल कीजिए।
और अगर आपको पता है कि कौन-से हिस्से आप हटाना चाहते हैं, तो split का इस्तेमाल कीजिए।
STRING | split(REGEX; FLAGS)
एक आर्गुमेंट वाला split फिल्टर अपने आर्गुमेंट को एक तय स्ट्रिंग मानता है।
split के साथ रेगेक्स इस्तेमाल करने के लिए दूसरा आर्गुमेंट देना ही होगा; खाली स्ट्रिंग देना भी ठीक है।
यह उदाहरण एक स्ट्रिंग को किसी भी खाली स्थान पर तोड़ता है।
"first second third fourth" | split("\\s+"; "")
# => ["first", "second", "third", "fourth"]
sub और gsub फिल्टर इनपुट स्ट्रिंग को बदल सकते हैं। इनपुट के जो हिस्से मैच हुए हैं, उनकी जगह ये एक रिप्लेसमेंट स्ट्रिंग रख देते हैं।
सिर्फ पहला मिलान बदलने के लिए sub का इस्तेमाल कीजिए।
सारे मिलान बदलने के लिए gsub का इस्तेमाल कीजिए।
STRING | sub(REGEX; REPLACEMENT)
STRING | sub(REGEX; REPLACEMENT; FLAGS)
STRING | gsub(REGEX; REPLACEMENT)
STRING | gsub(REGEX; REPLACEMENT; FLAGS)
"Goodnight kittens. Goodnight mittens." | sub("night"; " morning")
# => "Good morning kittens. Goodnight mittens."
"Goodnight kittens. Goodnight mittens." | gsub("night"; " morning")
# => "Good morning kittens. Good morning mittens."
रिप्लेसमेंट टेक्स्ट मैच हुई सबस्ट्रिंग को भी संदर्भित कर सकता है; इसके लिए नेम्ड कैप्चर और स्ट्रिंग इंटरपोलेशन का इस्तेमाल कीजिए।
"Some 3-letter acronyms: gnu, csv, png"
| gsub( "\\b(?<tla>[[:alpha:]]{3})\\b"; # find words 3 letters long
"\(.tla | ascii_upcase)" ) # upper-case the match
# => "Some 3-letter acronyms: GNU, CSV, PNG"
ऊपर के सभी फिल्टरों में FLAGS एक स्ट्रिंग है, जिसमें बताए गए फ्लैग शून्य या अधिक हो सकते हैं।
g - वैश्विक खोज (सारे मिलान ढूँढता है, सिर्फ पहला नहीं)i - केस-असंवेदनशील खोजm - मल्टी लाइन मोड ('.' न्यूलाइन से भी मैच करेगा)n - खाली मिलान अनदेखा करेंp - s और m, दोनों मोड चालूs - सिंगल लाइन मोड ('^' -> '\A', '$' -> '\Z')l - सबसे लंबे संभव मिलान ढूँढेंx - एक्सटेंडेड रेगेक्स फॉर्मैट (खाली स्थान और कमेंट अनदेखा करें)जैसे
"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")
# or with Extended formatting
"JIRAISSUE-1234" | capture("
(?<project> \\w+ ) # the Jira project
- # followed by a hyphen
(?<issue_num> \\d+ ) # followed by digits
"; "x")
एक कंपनी एक Chatbot विकसित कर रही है। उसने आपको रेगुलर एक्सप्रेशन विशेषज्ञ के रूप में नौकरी पर रखा है।
यह अभी विकास के बहुत शुरुआती दौर में है। आपको रेगुलर एक्सप्रेशन के ज़रिए Chatbot की प्राकृतिक भाषा समझने और बनाने की क्षमता बेहतर बनानी है।
समझदार होने के साथ-साथ Chatbot एक वफादार सहायक भी है। Chatbot से कुछ पूछने के लिए यूज़र को कमांड की पहली जगह पर "Chatbot" शब्द कहना ज़रूरी है। इससे कोई फर्क नहीं पड़ता कि कीवर्ड बड़े अक्षरों में है या छोटे अक्षरों में। अहम बात शब्द की जगह है।
फंक्शन is_valid_command बनाइए, जो Chatbot को यह पहचानने में मदद करता है कि यूज़र कब कमांड दे रहा है।
"Chatbot, play a song from the 80's." | is_valid_command
# => true
"Hey Chatbot, where is the closest pharmacy?" | is_valid_command
# => false
"CHATBOT, do you have a solution for this challenge?" | is_valid_command
# => true
इंसान अपनी भावनाएँ जताने के लिए इमोजी कैसे इस्तेमाल करते हैं, यह समझना Chatbot के लिए मुश्किल होता है। जब Chatbot को यूज़र के संदेश मिलते हैं, तो हर इमोजी "emoji" स्ट्रिंग के रूप में आता है, जिसके बाद एक id नंबर होता है।
मेथड remove_emoji बनाइए, जो एक स्ट्रिंग लेता है और संदेश में मौजूद सारे इमोजी हटा देता है।
जिन लाइनों में इमोजी नहीं हैं, वे बिना बदलाव के ही लौटाई जानी चाहिए। बस इमोजी स्ट्रिंग हटा दीजिए। खाली जगह में कोई बदलाव न कीजिए।
"I love playing videogames emoji3465 it's one of my hobbies" | remove_emoji
# => "I love playing videogames it's one of my hobbies"
Chatbot से बातचीत के दौरान किसी समय यूज़र उसे एक फोन नंबर देगा। Chatbot सिर्फ एक खास फॉर्मेट वाले नंबर पर ही कॉल कर सकता है।
फंक्शन check_phone_number बनाइए।
अगर नंबर मान्य है, तो Chatbot एक ऐसा संदेश भेजता है जिसमें वह यूज़र को धन्यवाद देता है और नंबर की पुष्टि करता है। अगर नंबर मान्य नहीं है, तो Chatbot यूज़र को बताता है कि फोन नंबर मान्य नहीं है।
अपेक्षित फॉर्मेट (+NN) NNN-NNN-NNN है, जिसमें N एक अंक है।
"chatbot my phone number is (+34) 659-771-594" | check_phone_number
# => "Thanks! Your phone number is OK."
"chatbot, call me at 659-771-594" | check_phone_number
# => "Oops, it seems like I can't reach out to 659-771-594."
Chatbot वाकई एक जिज्ञासु सॉफ्टवेयर है। हालाँकि यह किसी खास विषय को इंटरनेट पर खोज सकता है, फिर भी इसे यूज़र से ऐसी बढ़िया वेबसाइटों के बारे में पूछना पसंद है जहाँ जाकर काम की जानकारी मिल सके।
बातचीत का उदाहरण:
Chatbot: नमस्ते यूज़र, मैं JavaScript में कोड करना सीखना चाहता हूँ। क्या आप किसी ऐसी बढ़िया वेबसाइट के बारे में जानते हैं जहाँ से मैं सीख सकूँ?
यूज़र: मैंने exercism.org से बहुत कुछ सीखा, वहाँ बहुत सारी बढ़िया चीज़ें हैं।
फंक्शन get_domains बनाइए, जो वेबसाइट डोमेन का एक ऐरे लौटाता है।
"I learned a lot from exercism.org and google.com" | get_domains
# => ["exercism.org", "google.com"]
एक विनम्र Chatbot यूज़र को नाम लेकर संबोधित करता है। जब कोई यूज़र अपना परिचय देता है, तो हमारा Chatbot उसका नाम पहचानकर एक दोस्ताना अभिवादन के साथ जवाब देता है।
फंक्शन nice_to_meet_you लिखिए।
अगर इनपुट स्ट्रिंग में "My name is Someone." मौजूद है, तो नाम निकालिए और "Nice to meet you, Someone." स्ट्रिंग लौटाइए।
"My name is Jean-Luc" | nice_to_meet_you
# => "Nice to meet you, Jean-Luc"
"फीचर जोड़ने की बढ़ती लत" के आगे झुकते हुए, हम Chatbot में एक CSV पार्सिंग फंक्शन जोड़ेंगे।
फंक्शन parse_csv बनाइए, जो एक स्ट्रिंग लेता है और उससे बने फील्ड का एक ऐरे लौटाता है।
फील्ड विभाजक "कॉमा और उसके बाद वैकल्पिक खाली जगह" होना चाहिए।
CSV फॉर्मेट के किसी भी एज केस की हमें चिंता नहीं करनी है (जैसे कि ऐसे फील्ड जिनमें कॉमा हों)।
"first, second,third, fourth" | parse_csv
# => ["first", "second", "third", "fourth"]
Exercism पर साइन अप कीजिए और jq को 12 कॉन्सेप्ट75 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।