रेगुलर एक्सप्रेशन स्ट्रिंग्स पर पैटर्न मैच करने का एक बहुत उपयोगी तरीका है। इसके लिए एक खास तरह की भाषा (DSL) बनाई गई है, जो सिर्फ इसी काम के लिए है।
कई दूसरी प्रोग्रामिंग भाषाओं की तरह Julia अपनी खुद की Regex लाइब्रेरी बनाने की कोशिश नहीं करती। इसके बजाय यह लोकप्रिय PCRE2 लाइब्रेरी को रैप करती है, जिससे इसका Regex सिंटैक्स (जैसे कि) Gleam जैसा ही और JavaScript से बहुत मिलता-जुलता बनता है।
इस Julia सिलेबस में यह मान लिया गया है कि आप बुनियादी Regex सिंटैक्स से पहले से परिचित हैं। हम सिर्फ Julia से जुड़ी खास बातों पर ध्यान देंगे।
अपने रेगुलर एक्सप्रेशन के ज्ञान को ताज़ा करने के लिए कुछ संसाधन नीचे दिए गए हैं।
रेगुलर एक्सप्रेशन के लिए Julia का इंटरफेस मैनुअल में समझाया गया है।
Julia में रेगुलर एक्सप्रेशन बस एक स्ट्रिंग ही है, और उसके शुरू के " से पहले r लगाना होता है।
इसकी सभी बुनियादी सुविधाएँ स्टैंडर्ड लाइब्रेरी में ही मौजूद हैं।
वास्तव में, Strings कॉन्सेप्ट में बताए गए कई फंक्शन पहले से ही Regex खोज के लिए बने हैं, जैसे occursin().
julia> re = r"test$"
r"test$"
julia> typeof(re)
Regex
# Does a string end with "test"?
julia> occursin(re, "this is a test")
true
julia> occursin(re, "these are tests")
false
क्लोज़िंग कोट के बाद मॉडिफायर अक्षर भी लग सकते हैं, जैसे i लगाने पर मैच में अक्षरों के बड़े-छोटे होने से फर्क नहीं पड़ता।
julia> occursin(r"test", "Testing")
false
julia> occursin(r"test"i, "Testing")
true
आम तौर पर हमें यह जानना होता है कि क्या मैच हुआ। इसके लिए रेगुलर एक्सप्रेशन के अंदर गोल ब्रैकेटों में कैप्चर ग्रुप डाले जाते हैं, और फिर match() फंक्शन इस्तेमाल किया जाता है।
julia> m = match(r"(\d+g) .* (\d+ml)", "dissolve 25g sugar in 200ml water")
RegexMatch("25g sugar in 200ml", 1="25g", 2="200ml")
julia> m.captures
2-element Vector{Union{Nothing, SubString{String}}}:
"25g"
"200ml"
# how many matches?
julia> length(m.captures)
2
# what matched?
julia> m[1], m[2]
("25g", "200ml")
# Starting positions of the matches (character index)
julia> m.offsets
2-element Vector{Int64}:
10
23
ऐसा भी हो सकता है कि मैच न मिले।
तब नतीजा RegexMatch की जगह खास वैल्यू Nothing होता है, इसलिए इसकी जाँच के लिए तैयार रहिए।
# failed match
m = match(r"(not here)", "dissolve 25g sugar in 200ml water")
julia> typeof(m)
Nothing
julia> isnothing(m)
true
हालाँकि match डिफॉल्ट रूप से स्ट्रिंग की शुरुआत से ढूँढना शुरू करता है, हम एक ऑफसेट n भी दे सकते हैं, जिससे पहले n अक्षर छोड़ दिए जाएँ।
# capture first match
julia> m = match(r"(\wat)", "cat, sat, mat")
RegexMatch("cat", 1="cat")
# ignore first 5 characters, then match
julia> m = match(r"(\wat)", "cat, sat, mat", 5)
RegexMatch("sat", 1="sat")
Julia में match() लक्ष्य स्ट्रिंग में सिर्फ पहला मैच ही ढूँढता है। कुछ दूसरी भाषाओं की तरह यहाँ कोई ग्लोबल मॉडिफायर नहीं होता।
इसके बजाय eachmatch() है, जो मैचों का इटरेटर लौटाता है।
यह लेज़ी तरीके से चलता है, इसलिए आपको इसे अपनी ज़रूरत के फॉर्मेट में बदलना पड़ सकता है।
julia> matches = eachmatch(r"(\wat)", "cat, sat, mat")
Base.RegexMatchIterator{String}(r"(\wat)", "cat, sat, mat", false)
# convert to vector
julia> collect(matches)
3-element Vector{RegexMatch}:
RegexMatch("cat", 1="cat")
RegexMatch("sat", 1="sat")
RegexMatch("mat", 1="mat")
# convert with comprehension
julia> [m.match for m in matches]
3-element Vector{SubString{String}}:
"cat"
"sat"
"mat"
# broadcast an anonymous function
julia> (m -> m.match).(matches)
3-element Vector{SubString{String}}:
"cat"
"sat"
"mat"
Regex इस्तेमाल करने की एक आम वजह है मैच को किसी दूसरी स्ट्रिंग से बदल देना।
replace() फंक्शन के बारे में Strings कॉन्सेप्ट में बताया गया था, जहाँ खोजने के लिए स्ट्रिंग लिटरल इस्तेमाल होते हैं।
यही फंक्शन Regex मैचिंग की पूरी शक्ति का फायदा उठा सकता है।
julia> replace("some string", r"[aeiou]" => "*")
"s*m* str*ng"
julia> replace("first second", r"(\w+) (?<agroup>\w+)" => s"\g<agroup> \1")
"second first"
ऊपर का दूसरा उदाहरण दिखाता है कि बदलाव में क्रमांकित और नाम वाले, दोनों तरह के कैप्चर ग्रुप कैसे इस्तेमाल किए जा सकते हैं, और यह सब s" " स्ट्रिंग के अंदर होता है।
ज़्यादा जानकारी के लिए मैनुअल देखिए। यह ऐसा विषय है जो ज़्यादातर प्रोग्रामरों को बार-बार डॉक्युमेंटेशन देखने पर मजबूर कर देता है!
आपको एक ऐसी कंपनी ने रेगुलर एक्सप्रेशन विशेषज्ञ के तौर पर नौकरी पर रखा है जो एक चैटबॉट बना रही है।
यह अभी विकास के बहुत शुरुआती चरण में है। इसलिए आपका काम रेगुलर एक्सप्रेशन का उपयोग करके चैटबॉट की प्राकृतिक भाषा को समझने और बनाने की क्षमता को बेहतर बनाना है।
सीखने के उद्देश्य से, कृपया इन कार्यों को रेगुलर एक्सप्रेशन की मदद से हल कीजिए।
हम जानते हैं कि कभी-कभी दूसरे तरीके भी संभव होते हैं (और वे ज़्यादा तेज़ भी हो सकते हैं!)
समझदार होने के साथ-साथ चैटबॉट एक वफादार सहायक भी है।
चैटबॉट से कुछ पूछने के लिए उपयोगकर्ता को कमांड में सबसे पहले “Chatbot” शब्द कहना होता है।
इससे कोई फर्क नहीं पड़ता कि यह कीवर्ड बड़े अक्षरों में है या छोटे अक्षरों में। यहाँ ज़रूरी बात शब्द की जगह है।
is_valid_command() फंक्शन बनाइए जो चैटबॉट को यह पहचानने में मदद करता है कि उपयोगकर्ता कोई कमांड दे रहा है।
julia> is_valid_command("Chatbot, play a song from the 80's.")
True
julia> is_valid_command("Hey Chatbot, where is the closest pharmacy?")
False
julia> is_valid_command("CHATBOT, do you have a solution for this challenge?")
True
चैटबॉट के लिए यह समझना मुश्किल होता है कि इंसान अपनी भावनाएँ जताने के लिए इमोजी का इस्तेमाल कैसे करते हैं।
जब चैटबॉट को उपयोगकर्ता के संदेश मिलते हैं, तो हर इमोजी को “emoji” के रूप में दिखाया जाता है और उसके बाद उसका id नंबर आता है।
remove_emoji() मेथड बनाइए जो एक स्ट्रिंग लेता है और संदेश में से हर इमोजी का एन्क्रिप्शन हटा देता है।
जिन पंक्तियों में इमोजी का यह टेक्स्ट नहीं है, वे बिना किसी बदलाव के लौटाई जानी चाहिए।
सिर्फ इमोजी स्ट्रिंग हटाइए। खाली जगह को ठीक करने की कोशिश न कीजिए।
julia> remove_emoji("I love playing videogames emoji3465 it's one of my hobbies")
"I love playing videogames it's one of my hobbies"
चूँकि मोबाइल ऐप पर चैटबॉट के फीचर डाउनलोड किए जा सकते हैं, इसलिए बातचीत के दौरान उपयोगकर्ता से फोन नंबर लिखने की अपेक्षा की जाती है।
समस्या यह है कि चैटबॉट सिर्फ एक खास फॉर्मैट वाले नंबर को ही पढ़ और जाँच सकता है।
अगर नंबर वैध है (यानी वह उस अक्षर-क्रम से मेल खाता है जो रेगुलर एक्सप्रेशन तय करता है), तो चैटबॉट उपयोगकर्ता को धन्यवाद देते हुए और नंबर की पुष्टि करते हुए एक संदेश भेजता है। अगर नंबर अवैध है, तो फंक्शन उपयोगकर्ता को बताता है कि फोन नंबर वैध नहीं है।
अपेक्षित फॉर्मैट यह है: (+##) ###-###-###
julia> check_phone_number("(+34) 659-771-594")
"Thanks! You can now download me to your phone."
julia> check_phone_number("659-771-594")
"Oops, it seems like I can't reach out to 659-771-594"
चैटबॉट सचमुच एक जिज्ञासु सॉफ्टवेयर है। हालाँकि वह किसी खास विषय के बारे में इंटरनेट पर खोज सकता है, फिर भी उसे उपयोगकर्ताओं से अच्छी वेबसाइटों या URL के बारे में पूछना पसंद है ताकि वह ज़रूरी जानकारी ढूँढ सके।
बातचीत का उदाहरण:
getURL() फंक्शन बनाइए जो हर वेबसाइट के सिर्फ लिंक वाला एक ऐरे लौटाता है।
julia> getURL("I learned a lot from exercism.org")
["exercism.org"]
जिन सभी लोगों से बातचीत हुई है, उनका डेटा संग्रहीत करने के लिए चैटबॉट उपयोगकर्ता की प्रोफाइल से पूरा नाम इस तरह निकाल सकता है: “smith, john”।
इस तरह हम चाहते हैं कि हमारा चैटबॉट बहुत विनम्र रहे और अच्छी छाप छोड़े।
nice_to_meet_you() फंक्शन लिखिए जो उपयोगकर्ता के पूरे नाम वाली एक स्ट्रिंग लेता है और “Nice to meet you, John Smith” स्ट्रिंग लौटाता है।
julia> str = "Smith, John"
julia> nice_to_meet_you(str)
"Nice to meet you, John Smith"
Exercism पर साइन अप कीजिए और Julia को 35 कॉन्सेप्ट128 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।