मैंने सोचा कि रूबी में नियमित अभिव्यक्तियों के साथ आप कुछ अन्य साफ-सुथरी चाल देखकर रेगेक्स सशर्त के बारे में कल के लेख का पालन करना मजेदार होगा।
रेगुलर एक्सप्रेशन द्वारा स्ट्रिंग्स को विभाजित करना
आप शायद टेक्स्ट डिलीमीटर का उपयोग करके स्ट्रिंग्स को विभाजित करने से काफी परिचित हैं:
"one,two".split(",")
# => ["one", "two"]
लेकिन क्या आप जानते हैं कि स्प्लिट रेगुलर एक्सप्रेशन को भी स्वीकार करेगा?
# 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
like जैसा व्यवहार करने के लिए . नीचे दिए गए कोड में, मैं स्ट्रिंग को 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
. लिखते हैं रूबी में, हम पूछ रहे हैं "क्या बी ए द्वारा परिभाषित सेट में है"। या इस मामले में, "क्या 'हिहो' रेगेक्स /hi/
से मेल खाने वाले स्ट्रिंग्स के सेट से संबंधित है ".
===
रूबी के केस स्टेटमेंट में ऑपरेटर का आंतरिक रूप से उपयोग किया जाता है। इसका मतलब है कि आप केस स्टेटमेंट में भी रेगुलर एक्सप्रेशन का उपयोग कर सकते हैं।
case "hiho"
when /hi/
puts "match"
end
ट्रिपल-बराबर ऑपरेटर आपके अपने तरीकों को नियमित अभिव्यक्ति या स्ट्रिंग स्वीकार करने के लिए भी उपयोगी हो सकता है।
कल्पना करें कि जब कोई त्रुटि होती है तो आप कुछ कोड निष्पादित करना चाहते हैं, जब तक कि यह कक्षाओं की पूर्व-कॉन्फ़िगर सूची पर अनदेखा न हो। नीचे दिए गए उदाहरण में, हम ===
. का उपयोग करते हैं ऑपरेटर को उपयोगकर्ता को एक स्ट्रिंग, या एक नियमित अभिव्यक्ति निर्दिष्ट करने की अनुमति देने के लिए।
def ignored?(error)
@ignored_patterns.any? { |x| x === error.class.name }
end
बस इतना ही!
यह सुनिश्चित करने के लिए, रूबी और रेल में बिखरे हुए दर्जनों छोटी चालें हैं। अगर कोई आपको विशेष रूप से पसंद है, तो मुझे बताएं!