Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी नियमित अभिव्यक्तियों के अंदर सशर्त का उपयोग करना

2013 में रूबी 2.0 ने जिन कई नई विशेषताओं को वापस भेज दिया, उनमें से जिस पर मैंने कम से कम ध्यान दिया, वह था नया रेगुलर एक्सप्रेशन इंजन, ओनिग्मो। आखिरकार, रेगुलर एक्सप्रेशन रेगुलर एक्सप्रेशन हैं - मुझे इसकी परवाह क्यों करनी चाहिए कि रूबी उन्हें कैसे लागू करती है?

जैसा कि यह पता चला है, ओनिग्मो रेगेक्स इंजन की आस्तीन में कुछ साफ-सुथरी चालें हैं जिनमें आपके नियमित अभिव्यक्तियों के अंदर सशर्त उपयोग करने की क्षमता शामिल है।

इस पोस्ट में हम रेगेक्स कंडीशन्स के बारे में जानेंगे, रूबी द्वारा उनके कार्यान्वयन की विचित्रताओं के बारे में जानेंगे, और रूबी की सीमाओं के आसपास काम करने के लिए कुछ ट्रिक्स पर चर्चा करेंगे। आइए शुरू करें!

ग्रुप और कैप्चरिंग

रेगुलर एक्सप्रेशन में कंडीशनल को समझने के लिए, आपको सबसे पहले ग्रुपिंग और कैप्चरिंग को समझना होगा।

कल्पना कीजिए कि आपके पास अमेरिकी उद्धरणों की सूची है:

Fayetteville, AR
Seattle, WA

आप शहर के नाम को राज्य के संक्षिप्त नाम से अलग करना चाहेंगे। ऐसा करने का एक तरीका कई मैच करना है:

PLACE = "Fayetteville, AR"

# City: Match any char that's not a comma
PLACE.match(/[^,]+/) 
# => #<MatchData "Fayetteville">

# Separator: Match a comma and optional spaces
PLACE.match(/, */)
# => #<MatchData ", ">

# State: Match a 2-letter code at the end of the string. 
PLACE.match(/[A-Z]{2}$/) 
# => #<MatchData "AR">

यह काम करता है, लेकिन यह बहुत वर्बोज़ है। समूहों का उपयोग करके, आप केवल एक रेगुलर एक्सप्रेशन के साथ शहर और राज्य दोनों को कैप्चर कर सकते हैं।

तो चलिए ऊपर दिए गए रेगुलर एक्सप्रेशन को जोड़ते हैं, और प्रत्येक सेक्शन को कोष्ठकों से घेरते हैं। माता-पिता हैं कि आप चीजों को नियमित अभिव्यक्तियों में कैसे समूहित करते हैं।

PLACE = "Fayetteville, AR"
m = PLACE.match(/([^,]+)(, *)([A-Z]{2})/) 
# => #<MatchData "Fayetteville, AR" 1:"Fayetteville" 2:", " 3:"AR">

जैसा कि आप देख सकते हैं, उपरोक्त अभिव्यक्ति शहर और राज्य दोनों को दर्शाती है। आप MatchData . का इलाज करके उन तक पहुंच सकते हैं एक सरणी की तरह:

m[1]
# => "Fayetteville"
m[3]
# => "AR"

समूहीकरण के साथ समस्या, जैसा कि ऊपर किया गया है, यह है कि कैप्चर किए गए डेटा को एक सरणी में डाल दिया जाता है। यदि सरणी में इसकी स्थिति बदल जाती है, तो आपको अपना कोड अपडेट करना होगा या आपने अभी-अभी एक बग पेश किया है।

उदाहरण के लिए, हम यह तय कर सकते हैं कि ", " . को कैप्चर करना मूर्खतापूर्ण है पात्र। इसलिए हम रेगुलर एक्सप्रेशन के उस हिस्से के आसपास के माता-पिता को हटा देते हैं:

m = PLACE.match(/([^,]+), *([A-Z]{2})/) 
# => #<MatchData "Fayetteville, AR" 1:"Fayetteville" 2:"AR">

m[3]
# => nil

लेकिन अब m[3] अब राज्य - बग शहर शामिल नहीं है।

नामांकित समूह

आप रेगुलर एक्सप्रेशन समूहों को नाम देकर उन्हें अधिक अर्थपूर्ण बना सकते हैं। सिंटैक्स काफी हद तक हमारे द्वारा उपयोग किए जाने के समान है। हम रेगेक्स को माता-पिता में घेरते हैं, और इस तरह नाम निर्दिष्ट करते हैं:

/(?<groupname>regex)/

यदि हम इसे अपने शहर/राज्य रेगुलर एक्सप्रेशन पर लागू करते हैं, तो हमें यह प्राप्त होता है:

m = PLACE.match(/(?<city>[^,]+), *(?<state>[A-Z]{2})/)
# => #<MatchData "Fayetteville, AR" city:"Fayetteville" state:"AR">

और हम MatchData . का इलाज करके कैप्चर किए गए डेटा तक पहुंच सकते हैं हैश की तरह:

m[:city] 
# => "Fayetteville"

सशर्त

रेगुलर एक्सप्रेशन में कंडीशनल फॉर्म लेते हैं /(?(A)X|Y)/ . उनका उपयोग करने के कुछ मान्य तरीके यहां दिए गए हैं:

# If A is true, then evaluate the expression X, else evaluate Y
/(?(A)X|Y)/

# If A is true, then X
/(?(A)X)/

# If A is false, then Y
/(?(A)|Y)/

आपकी स्थिति के लिए सबसे आम विकल्पों में से दो, A हैं:

  • क्या कोई नामित या क्रमांकित समूह कैप्चर किया गया है?
  • क्या चारों ओर देखने का मूल्यांकन सत्य होता है?

आइए देखें कि उनका उपयोग कैसे करें:

क्या कोई समूह कैप्चर किया गया है?

किसी समूह की उपस्थिति की जांच करने के लिए, ?(n) . का उपयोग करें सिंटैक्स, जहां n एक पूर्णांक है, या समूह का नाम <> . से घिरा हुआ है या ''

# Has group number 1 been captured?
/(?(1)foo|bar)/

# Has a group named "mygroup" been captured?
/(?(<mygroup>)foo|bar)/

उदाहरण

कल्पना कीजिए कि आप यूएस टेलीफ़ोन नंबर पार्स कर रहे हैं। इन नंबरों में तीन अंकों का क्षेत्र कोड होता है जो तब तक वैकल्पिक होता है जब तक कि संख्या एक से शुरू न हो।

1-800-555-1212 # Valid
800-555-1212 # Valid
555-1212 # Valid

1-555-1212 # INVALID!!

संख्या 1 से शुरू होने पर ही हम क्षेत्र कोड को एक आवश्यकता बनाने के लिए एक सशर्त का उपयोग कर सकते हैं।

# This regular expression looks complex, but it's made of simple pieces
# `^(1-)?` Does the string start with "1-"? If so, capture it as group 1
# `(?(1)` Was anything captured in group one?
# `\d{3}-` if so, do a required match of three digits and a dash (the area code)
# `|(\d{3}-)?` if not, do an optional match of three digits and a dash (area code)
# `\d{3}-\d{4}` match the rest of the phone number, which is always required.

re = /^(1-)?(?(1)\d{3}-|(\d{3}-)?)\d{3}-\d{4}/

"1-800-555-1212".match(re)
#=> #<MatchData "1-800-555-1212" 1:"1-" 2:nil>

"800-555-1212".match(re)
#=> #<MatchData "800-555-1212" 1:nil 2:"800-">

"555-1212".match(re)
#=> #<MatchData "555-1212" 1:nil 2:nil>

"1-555-1212".match(re)
=> nil

सीमाएं

समूह-आधारित सशर्तों का उपयोग करने में एक समस्या यह है कि समूह से मेल खाने वाले स्ट्रिंग में उन वर्णों का "खपत" होता है। उन वर्णों का उपयोग सशर्त द्वारा नहीं किया जा सकता है।

उदाहरण के लिए, यदि टेक्स्ट "यूएसडी" मौजूद है, तो निम्न कोड 100 से मेल खाने की कोशिश करता है और विफल रहता है:

"100USD".match(/(USD)(?(1)\d+)/) # nil

पर्ल और कुछ अन्य भाषाओं में, आप अपने कंडीशनल में एक लुक-फ़ॉरवर्ड स्टेटमेंट जोड़ सकते हैं। यह आपको स्ट्रिंग में कहीं भी टेक्स्ट के आधार पर सशर्त ट्रिगर करने देता है। लेकिन रूबी के पास यह नहीं है, इसलिए हमें थोड़ा रचनात्मक होना होगा।

चारों ओर देखें

सौभाग्य से, हम लुक-अराउंड एक्सप्रेशन का दुरुपयोग करके रूबी के रेगेक्स सशर्त में सीमाओं के आसपास काम कर सकते हैं।

आसपास क्या है?

आम तौर पर, नियमित अभिव्यक्ति पार्सर मैचों की तलाश में शुरुआत से अंत तक आपकी स्ट्रिंग के माध्यम से कदम उठाता है। यह किसी शब्द संसाधक में कर्सर को बाएँ से दाएँ घुमाने जैसा है।

आगे-आगे और पीछे-पीछे के भाव थोड़े अलग तरीके से काम करते हैं। वे आपको किसी भी वर्ण का उपभोग किए बिना स्ट्रिंग का निरीक्षण करने देते हैं। जब वे कर लिए जाते हैं, तो कर्सर ठीक उसी स्थान पर छोड़ दिया जाता है जहां वह शुरुआत में था।

चारों ओर देखने के लिए एक महान परिचय के लिए, आगे देखने और पीछे देखने के लिए रेक्सग की मार्गदर्शिका देखें

सिंटैक्स ऐसा दिखता है:

<थ>वाक्यविन्यास
टाइप करें उदाहरण
आगे देखें (?=query) \d+(?= dollars) "100 डॉलर" में 100 से मेल खाता है
नकारात्मक नजरिया (?!query) \d+(?! dollars) 100 से मेल खाता है यदि इसके बाद "डॉलर" शब्द नहीं आता है
पीछे देखो (?<=query) (?<=lucky )\d "भाग्यशाली 7" में 7 से मेल खाता है
पीछे नकारात्मक नजरिया (?<!query) (?<!furious )\d "भाग्यशाली 7" में 7 से मेल खाता है

सशर्तों को बेहतर बनाने के लिए लुक-अराउंड का दुरुपयोग

हमारे सशर्त में, हम केवल उन समूहों के अस्तित्व को क्वेरी कर सकते हैं जो पहले ही सेट हो चुके हैं। आम तौर पर, इसका मतलब है कि समूह की सामग्री का उपभोग कर लिया गया है और सशर्त के लिए उपलब्ध नहीं है।

लेकिन आप बिना किसी वर्ण के समूह सेट करने के लिए लुक-फ़ॉरवर्ड का उपयोग कर सकते हैं! क्या आपका दिमाग अभी तक उड़ा है?

यह कोड याद रखें जो काम नहीं करता था?

"100USD".match(/(USD)(?(1)\d+)/) # nil

अगर हम समूह को आगे देखने के लिए इसे संशोधित करते हैं, तो यह अचानक ठीक काम करता है:

"100USD".match(/(?=.*(USD))(?(1)\d+)/)
=> #<MatchData "100" 1:"USD">

आइए उस क्वेरी को तोड़ दें और देखें कि क्या हो रहा है:

  • (?=.*(USD)) आगे की ओर देखते हुए, "USD" के लिए टेक्स्ट को स्कैन करें और इसे समूह 1 में कैप्चर करें
  • (?(1) अगर समूह 1 मौजूद है
  • \d+ फिर एक या अधिक संख्याओं का मिलान करें

बहुत साफ, हुह?


  1. जावास्क्रिप्ट रेगुलर एक्सप्रेशन

    रेगुलर एक्सप्रेशन एक खोज पैटर्न का वर्णन करने वाले वर्णों की एक स्ट्रिंग है। इस खोज पैटर्न का उपयोग यह निर्दिष्ट करने के लिए किया जाता है कि हम टेक्स्ट में क्या खोज रहे हैं। जावास्क्रिप्ट में रेगुलर एक्सप्रेशन के लिए कोड निम्नलिखित है - उदाहरण <!DOCTYPE html> <html lang="en">

  1. रूबी में लैम्ब्डा का उपयोग करना

    ब्लॉक रूबी का इतना महत्वपूर्ण हिस्सा हैं, उनके बिना भाषा की कल्पना करना मुश्किल है। लेकिन लैम्ब्डा? लैम्ब्डा को कौन प्यार करता है? आप एक का उपयोग किए बिना वर्षों तक जा सकते हैं। वे लगभग पुराने जमाने के अवशेष की तरह लगते हैं। ...लेकिन यह बिल्कुल सच नहीं है। एक बार जब आप उनकी थोड़ी जांच कर लेते हैं त

  1. रूबी नियमित अभिव्यक्तियों को माहिर करना

    रूबी रेगुलर एक्सप्रेशन (रूबी रेगेक्स संक्षेप में) आपको आगे की प्रक्रिया के लिए डेटा निकालने के इरादे से स्ट्रिंग्स के अंदर विशिष्ट पैटर्न खोजने में मदद करता है। रेगुलर एक्सप्रेशन के लिए दो सामान्य उपयोग के मामलों में सत्यापन और पार्सिंग शामिल हैं। उदाहरण के लिए : रूबी रेगेक्स . के साथ ईमेल पते के