2013-09-24 8 views
6

आज मैं निम्नलिखित नियमित अभिव्यक्ति में आए में एक परिमाणक रूप में इस्तेमाल किया और पता करने के लिए रूबी इसके साथ क्या करना होगा क्या चाहता है:अर्थ एक `+` के बाद एक `*` हुए, जब उसे एक रेगुलर एक्सप्रेशन

> "#a" =~ /^[\W].*+$/ 
=> 0 
> "1a" =~ /^[\W].*+$/ 
=> nil 

इस उदाहरण में, रूबी + चरित्र को अनदेखा कर रहा है। यदि यह गलत है, तो मुझे यकीन नहीं है कि यह इसके साथ क्या कर रहा है। मुझे लगता है कि इसे क्वांटिफायर के रूप में नहीं समझा जा रहा है, क्योंकि * बच निकला नहीं है और क्वांटिफायर के रूप में उपयोग किया जा रहा है। पर्ल/रूबी रेगेक्स में, कभी-कभी जब एक चरित्र (उदा।, -) का उपयोग उस संदर्भ में किया जाता है जिसमें इसे विशेष चरित्र के रूप में नहीं समझा जा सकता है, इसे शाब्दिक माना जाता है। लेकिन अगर यह इस मामले में हो रहा था, तो मैं उम्मीद करता हूं कि पहला मैच विफल हो जाएगा, क्योंकि lvalue स्ट्रिंग में + नहीं है।

क्या यह + चरित्र का एक संक्षिप्त रूप से सही उपयोग है? उपर्युक्त व्यवहार एक बग है? क्या मुझसे साफ़ - साफ़ कुछ चीज़ चूक रही है?

+0

आप इस रेगेक्स में कहां आए? –

+0

कुछ तीसरे पक्ष की सुरक्षा सामग्री में मेरे काम के दौरान सामना करना पड़ा। मैं अनुमान लगा रहा हूं कि रेगेक्स लेखक का इरादा नहीं है, लेकिन जब मैंने रुबी के व्यवहार को देखा, तो मुझे इस धारणा के बारे में प्रश्न पूछना शुरू हो गया। –

उत्तर

5

ठीक है, आप * के बाद निश्चित रूप से + का उपयोग कर सकते हैं। आप इसके बारे में कुछ पढ़ सकते हैं on this site* के बाद एक स्वामित्व वाले क्वांटिफ़ायर कहा जाता है।

यह क्या करता है? यह बैकट्रैकिंग से * को रोकता है।

साधारणतया, जब आप .*c की तरह कुछ और abcde मिलान करने के लिए इस का उपयोग कर, .* पहले पूरी स्ट्रिंग (abcde) से मेल खाएगा और regex .* के बाद c से मेल नहीं कर सकते हैं के बाद से, इंजन एक में वापस एक चरित्र जाना होगा यह जांचने का समय है कि कोई मैच है (यह बैकट्रैकिंग है)।

एक बार यह c पर वापस आ गया है, तो आपको abcde से abc मैच मिल जाएगा।

अब, कल्पना इंजन कुछ सौ पात्रों पीछे नहीं है, और यदि आप समूहों नेस्ट और कई * (या + या {m,n} फार्म) है, तो आप जल्दी से हजारों के साथ समाप्त कर सकते हैं, वर्ण के लाखों लोगों को पीछे, catastrophic backtracking कहा जाता है।

यह वह जगह है जहां स्वामित्व वाले क्वांटिफ़ायर काम में आते हैं। वे वास्तव में किसी भी प्रकार के बैकट्रैकिंग को रोकते हैं। मैंने उपरोक्त रेगेक्स में उल्लेख किया है, abcde.*+c से मेल नहीं खाया जाएगा। एक बार .*+ ने पूरी स्ट्रिंग का उपभोग किया है, यह बैकट्रैक नहीं कर सकता है और चूंकि स्ट्रिंग के अंत में c नहीं है, तो मिलान विफल हो जाता है।

तो, स्वामित्व वाले क्वांटिफ़ायर का एक और संभावित उपयोग यह है कि वे कुछ regexes के प्रदर्शन में सुधार कर सकते हैं, बशर्ते इंजन इसका समर्थन कर सके।

आपके रेगेक्स /^[\W].*+$/ के लिए, मुझे नहीं लगता कि इसमें कोई सुधार (शायद एक छोटा सा सुधार) है जो स्वामित्व वाले क्वांटिफ़ायर प्रदान करता है। और आखिरकार, इसे /^\W.*+$/ के रूप में आसानी से लिखा जा सकता है।

+0

आपको जो भी सुधार हो सकता है वह यह है कि इंजन को '। *' मिलान करने के दौरान मध्यवर्ती राज्यों को सहेजना नहीं पड़ता है (जिसे * बाद में बैकट्रैकिंग के लिए उपयोग किया जाएगा)।लेकिन पैटर्न किसी भी तरह से पीछे हटना नहीं होगा, इसलिए उस अंत में कोई बचत नहीं है। –

+0

उत्कृष्ट लेखन - धन्यवाद। –

+0

@EricWalker आपका स्वागत है :) – Jerry

संबंधित मुद्दे