मुझे लगा कि कल के रेगेक्स कंडीशनल के बारे में लेख का अनुसरण करते हुए रूबी में रेगुलर एक्सप्रेशन के साथ आप कुछ अन्य अच्छी ट्रिक्स कर सकते हैं, उन्हें देखना मजेदार होगा।
रेगुलर एक्सप्रेशन के माध्यम से स्ट्रिंग्स विभाजित करना
आप शायद टेक्स्ट डिलीमीटर का उपयोग करके स्ट्रिंग्स को विभाजित करने से काफी परिचित हैं:
"one,two".split(",") # => ["one", "two"]
लेकिन क्या आप जानते हैं कि split एक रेगुलर एक्सप्रेशन भी स्वीकार करेगा?
# use `,` and `-` as delimiters "one,two-three".split(/,|-/) => ["one", "two", "three"] # Use comma as thousands separator for US currency, # but use a space for Euros "1,000USD".split /(?=.*(USD))(?(1),| )/
डिलीमीटर कैप्चर करना
यहाँ एक अच्छी पार्टी ट्रिक है। आम तौर पर, जब आप एक स्ट्रिंग को विभाजित करते हैं, तो डिलीमीटर गायब हो जाते हैं:
# The commas vanish! "one,two".split(",") # => ["one", "two"]
लेकिन अगर आप एक रेगुलर एक्सप्रेशन का उपयोग करते हैं और आप डिलीमीटर को एक समूह के अंदर रखते हैं, तो split डिलीमीटर को भी कैप्चर करेगा।
"one,two-three".split(/(,|-)/) => ["one", ",", "two", "-", "three"]
ऐसा इसलिए होता है क्योंकि split वास्तव में प्रत्येक कैप्चर ग्रुप की सीमा पर स्ट्रिंग को विभाजित करता है।
Split का दुरुपयोग
आप split का दुरुपयोग करके इसे match की तरह व्यवहार करने के लिए मजबूर कर सकते हैं। नीचे दिए गए कोड में, मैं स्ट्रिंग को 4 टुकड़ों में विभाजित करने के लिए रेगुलर एक्सप्रेशन में चार समूहों का उपयोग कर रहा हूँ।
"1-800-555-1212".split(/(1)-(\d{3})-(\d{3})-(\d{4})/) => ["", "1", "800", "555", "1212"]
परिणामी सरणी में पहला आइटम एक खाली स्ट्रिंग है क्योंकि रेगुलर एक्सप्रेशन पूरे स्रोत स्ट्रिंग से मेल खाता है।
ग्लोबल मिलान
डिफ़ॉल्ट रूप से, रेगुलर एक्सप्रेशन केवल एक पैटर्न से एक बार मेल खाएंगे। नीचे दिए गए कोड में, हमें केवल एक मैच मिलता है भले ही पांच संभावित मैच हों।
"12345".match /\d/ => #<MatchData "1">
पर्ल जैसी अन्य भाषाओं में, समाधान रेगुलर एक्सप्रेशन को "ग्लोबल" के रूप में फ्लैग करना होगा। रूबी में वह विकल्प नहीं है, लेकिन इसमें String#scan मेथड है।
scan मेथड सभी मैचों को समाहित करने वाली एक सरणी लौटाता है:
"12345".scan /\d/ => ["1", "2", "3", "4", "5"]
इसमें एक आसान ब्लॉक सिंटैक्स भी है:
"12345".scan /\d/ do |i| puts i end
दुर्भाग्य से, स्ट्रिंग को आलसी तरीके से स्कैन करने का कोई तरीका नहीं लगता। इसलिए यह तकनीक शायद - कहने के लिए - 500mb फाइल को प्रोसेस करने के लिए उपयुक्त नहीं है।
समूहों के साथ स्कैनिंग
अब इस बिंदु पर मुझे आशा है कि आप सोच रहे होंगे कि हम अपने स्कैन में समूहों का उपयोग करके किस तरह की अजीब ट्रिक्स कर सकते हैं।
दुर्भाग्य से, यहां व्यवहार पूरी तरह से अनुमानित और उबाऊ है। समूहों के परिणामस्वरूप एक बहुआयामी सरणी होती है:
"hiho hiho".scan /(hi)(ho)/ => [["hi", "ho"], ["hi", "ho"]]
एक अजीब एज केस है। यदि आप समूहों का उपयोग करते हैं, तो समूह में नहीं होने वाली किसी भी चीज़ को वापस नहीं किया जाएगा।
"hiho hiho".scan /(hi)ho/ => [["hi"], ["hi"]]
संक्षिप्त रूप
मुझे यकीन है कि आप =~ के बारे में जानते हैं कि यह जांचने का एक तरीका है कि कोई रेगुलर एक्सप्रेशन किसी स्ट्रिंग से मेल खाता है या नहीं। यह उस वर्ण का इंडेक्स लौटाता है जहां मैच शुरू होता है।
"hiho" =~ /hi/ # 0 "hiho" =~ /ho/ # 2
मैच की जांच करने का एक और त्वरित तरीका है। मैं === ऑपरेटर की बात कर रहा हूँ।
/hi/ === "hiho" # true
जब हम रूबी में a === b लिखते हैं, तो हम पूछ रहे होते हैं "क्या b, a द्वारा परिभाषित सेट से संबंधित है"। या इस मामले में, "क्या 'hiho' रेगेक्स /hi/ से मेल खाने वाले स्ट्रिंग्स के सेट से संबंधित है"।
=== ऑपरेटर का उपयोग रूबी के केस स्टेटमेंट में आंतरिक रूप से किया जाता है। इसका मतलब है कि आप केस स्टेटमेंट में रेगुलर एक्सप्रेशन का भी उपयोग कर सकते हैं।
case "hiho" when /hi/ puts "match" end
ट्रिपल-इक्वल्स ऑपरेटर आपके अपने मेथड को या तो रेगुलर एक्सप्रेशन या स्ट्रिंग स्वीकार करने देने के लिए भी उपयोगी हो सकता है।
कल्पना करें कि आप तब कुछ कोड निष्पादित करना चाहते हैं जब कोई एरर होता है, जब तक कि यह अनदेखा करने के लिए पूर्व-कॉन्फ़िगर की गई क्लास की सूची में न हो। नीचे दिए गए उदाहरण में, हम उपयोगकर्ता को या तो एक स्ट्रिंग या एक रेगुलर एक्सप्रेशन निर्दिष्ट करने की अनुमति देने के लिए === ऑपरेटर का उपयोग करते हैं।
def ignored?(error) @ignored_patterns.any? { |x| x === error.class.name } end
बस इतना ही!
निश्चित रूप से, रूबी और रेल्स में बिखरे हुए ऐसी दर्जनों छोटी ट्रिक्स हैं। अगर आपके पास कोई विशेष पसंद है, तो मुझे बताएं!