लालची बनाम अनिच्छुक बनाम संभावित मात्रात्मक


357

मुझे नियमित अभिव्यक्तियों पर यह उत्कृष्ट ट्यूटोरियल मिला और जब मैं सहजता से समझ गया कि "लालची", "अनिच्छुक" और "अधिकारी" मात्रात्मक क्या करते हैं, तो मेरी समझ में एक गंभीर छेद प्रतीत होता है।

विशेष रूप से, निम्नलिखित उदाहरण में:

Enter your regex: .*foo  // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.

स्पष्टीकरण में पूरे इनपुट स्ट्रिंग को खाने का उल्लेख है , पत्रों का सेवन किया गया है , मिलान करने वाले का समर्थन किया गया है , "फू" की सही घटना को फिर से संगठित किया गया है , आदि।

दुर्भाग्य से, अच्छा रूपकों के बावजूद, मुझे अभी भी समझ में नहीं आया है कि किसके द्वारा खाया जाता है ... क्या आपको एक और ट्यूटोरियल के बारे में पता है जो बताता है (संक्षेप में) कैसे नियमित अभिव्यक्ति इंजन काम करते हैं?

वैकल्पिक रूप से, यदि कोई व्यक्ति निम्नलिखित पैराग्राफ को कुछ अलग-अलग वाक्यांशों में समझा सकता है, तो इसकी बहुत सराहना की जाएगी:

पहला उदाहरण लालची क्वांटिफायर का उपयोग करता है। * "कुछ भी", शून्य या अधिक बार खोजने के लिए, उसके बाद "एफ" "ओ" "ओ" अक्षर। क्‍योंकि क्‍वांटिफायर लालची होता है। * * एक्‍सप्रेशन का हिस्‍सा पहले पूरे इनपुट स्ट्रिंग को खाता है। इस बिंदु पर, समग्र अभिव्यक्ति सफल नहीं हो सकती है, क्योंकि पिछले तीन अक्षर ("एफ" "ओ" "ओ") पहले ही भस्म हो चुके हैं ( किसके द्वारा? )। इसलिए मिलान करने वाला धीरे-धीरे बंद हो जाता है ( दाएं-से-बाएं? ) एक समय में एक अक्षर जब तक "फू" की सबसे दाहिनी घटना को पुनर्जीवित नहीं किया जाता है ( इसका क्या मतलब है? ), जिस बिंदु पर मैच सफल होता है और खोज समाप्त होती है।

दूसरा उदाहरण, हालांकि, अनिच्छुक है, इसलिए यह पहले उपभोग से शुरू होता है ( किसके द्वारा? ) "कुछ भी नहीं"। क्योंकि "फू" स्ट्रिंग की शुरुआत में प्रकट नहीं होता है, इसे निगलने के लिए मजबूर किया जाता है ( कौन निगलता है?) पहला अक्षर (एक "x"), जो 0 और 4 पर पहले मैच को ट्रिगर करता है। हमारी टेस्ट हार्नेस प्रक्रिया जारी रहती है जब तक इनपुट स्ट्रिंग समाप्त नहीं हो जाती। यह 4 और 13 में एक और मैच पाता है।

तीसरा उदाहरण एक मैच खोजने में विफल रहता है क्योंकि क्वांटिफायर का अधिकारी है। इस स्थिति में, पूरे इनपुट स्ट्रिंग का सेवन किया जाता है। * + (( कैसे? ) को अभिव्यक्ति के अंत में "फू" को संतुष्ट करने के लिए कुछ भी नहीं छोड़ा जाता है। उन स्थितियों के लिए एक परिमाणी मात्रात्मक का उपयोग करें, जहाँ आप बिना किसी चीज़ के सभी को जब्त करना चाहते हैं ( मतलब बंद का मतलब क्या है ;); यह उन मामलों में बराबर लालची क्वांटिफायर से आगे निकल जाएगा, जहां मैच तुरंत नहीं मिला है।


22
मैक्सिमल क्वांटिफायर जैसे *, +और लालची? होते हैं मिनिमल क्वांटिफायर जैसे *?, +?और आलसी?? होते हैं अधिकार परिमाणकों तरह *+, ++है, और ?+कर रहे हैं चिपचिपा।
tchrist

6
यह सवाल "क्वांटिफायर> डिफरेंस ऑन मोर ..." के तहत स्टैक ओवरफ्लो रेगुलर एक्सप्रेशन एफएक्यू में जोड़ा गया है ।
aliteralmind

ब्याज की: जावा ™ ट्यूटोरियल - लालची, अनिच्छुक और संभावित मात्रात्मक के बीच अंतर - अनुभाग देखने के लिए नीचे स्क्रॉल करें।
गाइ कोडर

जवाबों:


495

मैं इसे एक शॉट दूँगा।

एक लालची क्वांटिफायर पहले जितना संभव हो उतना मेल खाता है। तो .*पूरे स्ट्रिंग से मेल खाता है। तब मिलानकर्ता fनिम्नलिखित का मिलान करने का प्रयास करता है , लेकिन कोई वर्ण नहीं बचा है। तो यह "बैकट्रैक" है, जिससे लालची क्वांटिफायर एक कम चरित्र से मेल खाता है (स्ट्रिंग बेमिसाल के अंत में "ओ" छोड़कर)। यह अभी भी fरेगेक्स में मेल नहीं खाता है , इसलिए यह एक और कदम पीछे करता है, जिससे लालची क्वांटिफायर फिर से एक कम चरित्र से मेल खाता है (स्ट्रिंग बेजोड़ के अंत में "ऊ" को छोड़कर)। यह अभी भीf रेगेक्स में मेल नहीं खाता है , इसलिए यह एक और कदम पीछे छोड़ता है (स्ट्रिंग के अंत में "फू" को छोड़कर) बेजोड़। अब, रेज़र अंत fमें रेगेक्स में मैच करता है,ooभी मेल खाते हैं। सफलता!

एक अनिच्छुक या "गैर लालची" परिमाणक पहले मैचों संभव के रूप में छोटे रूप में। तो .*पहले ही मैच में कुछ भी नहीं बचा, जिससे पूरा स्ट्रिंग बेमिसाल हो गया। तब मिलानकर्ता fनिम्नलिखित का मिलान करने का प्रयास करता है , लेकिन स्ट्रिंग का बेजोड़ भाग "x" से शुरू होता है ताकि काम न करे। तो मैचर बैकट्रैक, गैर-लालची क्वांटिफायर एक और चरित्र से मेल खाता है (अब यह "x" से मेल खाता है, "फॉक्सोक्सएक्सएक्सएक्सफ़ू" बेमिसाल है)। फिर यह मैच करने की कोशिश करता है f, जो सफल होता है, और रेगेक्स मैच में भी oअगला oहोता है। सफलता!

आपके उदाहरण में, यह उसी प्रक्रिया के बाद स्ट्रिंग के शेष बेजोड़ हिस्से "xxxxxxfoo" के साथ शुरू होता है।

एक प्रथक क्वांटिफायर लालची क्वांटिफायर की तरह ही है, लेकिन यह पीछे नहीं हटता है। तो यह .*पूरी स्ट्रिंग के मिलान के साथ शुरू होता है , जिसमें कुछ भी नहीं है। फिर fरेगेक्स के साथ मिलान करने के लिए इसके लिए कुछ भी नहीं बचा है । चूँकि एक अधिकारी के पास पर्याप्त मात्रा नहीं होती है, इसलिए मैच विफल हो जाता है।


15
+1 अच्छा जवाब। मैं केवल जोड़ना चाहूंगा: गो
मास्टेरिंग

@Anomie थोड़ी देर से लेकिन, मेरे पास के हिस्से में, मुझे लगता है कि आपका मतलब है इसलिए यह शुरू होता है .*+ (नोटिस "+")
RD

3
क्या वास्तव में रखने योग्य मात्रात्मक करता है? अगर यह इससे मेल नहीं खाता है? (मेरा मतलब है कि इसका महत्व समझ में, यदि आप इसे बाद वर्ण नहीं हो सकते है)
relipse

4
@relipse: आप इसे ऐसी स्थिति में उपयोग करेंगे जहां आप जानते हैं कि बैकग्राउंडिंग मदद नहीं करेगा, शायद .*+वह सब कुछ मैच के साथ न हो । उदाहरण के लिए, यदि आपके पास एक पैटर्न है [xyz]*foo, तो कोई ऐसा तरीका नहीं है जो कि x, y, और z के मिलान से [xyz]*थोड़ा पीछे हो fooजाए, तो निम्नलिखित बिट को मिलान करने की अनुमति देगा , जिससे आप चीजों को गतिवान बना सकते हैं।
एनोमी

4
@ मडबूम, शून्य मामले कभी (गणितीय तथ्य) होते हैं, जहां पर अधिकार रखने वाले क्वांटिफायर एक मैच का उत्पादन करेंगे, जो साधारण लालची क्वांटिफायर द्वारा उत्पादित नहीं किया जाएगा। कभी-कभी ऐसे मामलों में जहां वे एक का उत्पादन करेगा कर रहे हैं कोई मुकाबला नहीं जब लालची परिमाणकों एक उत्पादन होगा मैच। अन्य सभी मामलों के लिए (जहां लालची और व्यक्ति एक ही परिणाम का उत्पादन करते हैं), अधिकार प्राप्त मात्रात्मकता एक प्रदर्शन लाभ देती है।
वाइल्डकार्ड

49

दृश्य की कल्पना करने के लिए यह सिर्फ मेरा अभ्यास आउटपुट है-

दृश्य छवि


3
सिवाय इसके कि मुझे लगता है कि आखिरी मामला, अधिकारहीन, पास नहीं होना चाहिए - बस एक ही बार में पूरे स्ट्रिंग को पकड़ो।
अच्छी तरह से अपने mods इलाज

@ मुझे लगता है कि यह अब ठीक है?
SIslam

1
दृश्य स्पष्टीकरण के लिए धन्यवाद :)
लार्स मोएलेकेन

में EXPRESSION .*?foo(), आयतें [f] [o] [o]पीले रंग की नहीं होनी चाहिए 5th pass?
टोनिक्स

1
@tonix हाँ! पीला रंग अभिव्यक्ति में मिलान भाग के लिए किया जाना चाहिए .*?fooऔर .*+foo
SIslam

24

मैंने इससे पहले सटीक शब्दों को itate regurgitate ’या off backing off’ नहीं सुना है; यह वाक्यांश जो इनकी जगह लेगा, वह "बैकट्रैकिंग" है, लेकिन 'रीग्रिगेट' ऐसा लगता है जैसे किसी वाक्यांश के लिए "कंटेंट जिसे पहले से ही स्वीकार कर लिया गया था, जिसे बैकट्रैकिंग से पहले इसे फिर से फेंक दिया गया था"।

अधिकांश रेगेक्स इंजनों के बारे में महसूस करने के लिए महत्वपूर्ण बात यह है कि वे पीछे हट रहे हैं : वे रेगेक्स की संपूर्ण सामग्री से मिलान करने की कोशिश करते हुए एक संभावित, आंशिक मैच को अस्थायी रूप से स्वीकार करेंगे । यदि रेगेक्स को पहले प्रयास में पूरी तरह से मिलान नहीं किया जा सकता है, तो रेगेक्स इंजन उसके एक मैच पर वापस आ जाएगा । यह मिलान की कोशिश करेंगे *, +, ?, प्रत्यावर्तन, या {n,m}पुनरावृत्ति को अलग ढंग से, और फिर कोशिश करें। (और हां, इस प्रक्रिया में लंबा समय लग सकता है ।)

पहला उदाहरण लालची क्वांटिफायर का उपयोग करता है। * "कुछ भी", शून्य या अधिक बार खोजने के लिए, उसके बाद "एफ" "ओ" "ओ" अक्षर। क्योंकि क्वांटिफायर लालची होता है। * अभिव्यक्ति का हिस्सा पहले पूरे इनपुट स्ट्रिंग को खाता है। इस बिंदु पर, समग्र अभिव्यक्ति सफल नहीं हो सकती है, क्योंकि पिछले तीन अक्षर ("एफ" "ओ" "ओ") पहले ही भस्म हो चुके हैं ( किसके द्वारा? )।

पिछले तीन पत्र, f, o, और oपहले से ही प्रारंभिक द्वारा खपत थे .*शासन का कोई भाग। हालांकि, रेगेक्स में अगला तत्व, fइनपुट स्ट्रिंग में कुछ भी नहीं बचा है। इंजन को अपने प्रारंभिक मैच में बैकट्रैक करने के लिए मजबूर किया जाएगा .*, और सभी-लेकिन-अंतिम चरित्र का मिलान करने का प्रयास करें। (हो सकता है कि यह स्मार्ट हो और ऑल-बैक-ऑफ-द-थ्री तीन हो, क्योंकि इसमें तीन शाब्दिक शब्द हैं, लेकिन मैं इस स्तर पर कार्यान्वयन विवरण से अनजान हूं।)

तो मिलान करने वाला धीरे-धीरे बंद हो जाता है ( दाएं-से-बाएं? ) एक समय में एक अक्षर जब तक "फू" की सबसे दाहिनी घटना को पुनर्जीवित नहीं किया गया है ( इसका क्या मतलब है? ), जिस पर।

इसका मतलब है कि मिलान करते समय अस्थायी रूप से शामिल किया गया fooथा । क्योंकि वह प्रयास विफल हो गया था, रेगेक्स इंजन एक कम चरित्र को स्वीकार करने की कोशिश करता है । अगर वहाँ एक सफल मैच किया गया था इससे पहले कि इस उदाहरण में, तो इंजन शायद छोटा करने की कोशिश करेंगे मैच (से सही-से-बाएँ, जैसा कि आप ने कहा, क्योंकि यह एक लालची क्वालीफायर है), और अगर यह मैच करने में असमर्थ था पूरे आदानों, तो यह करने के लिए मजबूर किया जा सकता है का पुनर्मूल्यांकन करने का क्या यह मिलान किया था इससे पहले कि मेरी काल्पनिक उदाहरण में।.*.*.*.*.*

बिंदु मैच सफल होता है और खोज समाप्त होती है।

दूसरा उदाहरण, हालांकि, अनिच्छुक है, इसलिए यह पहले उपभोग से शुरू होता है ( किसके द्वारा? ) "कुछ भी नहीं"। क्योंकि "फू"

प्रारंभिक कुछ भी नहीं खाया जाता है .?*, जो कि कुछ भी संभव कम से कम राशि का उपभोग करेगा जो बाकी के रेगेक्स को मैच करने की अनुमति देता है।

स्ट्रिंग की शुरुआत में प्रकट नहीं होता है, इसे निगलने के लिए मजबूर किया जाता है ( कौन निगलता है?)

.?*कम से कम संभव मैच के साथ पूरे रेगेक्स से मिलान करने में प्रारंभिक विफलता पर बैकट्रैकिंग के बाद फिर से पहले चरित्र का उपभोग करता है। (इस मामले में, रेगेक्स इंजन .*?बाएं से दाएं के लिए मैच का विस्तार कर रहा है , क्योंकि .*?अनिच्छुक है।)

पहला अक्षर (एक "x"), जो 0 और 4 पर पहले मैच को ट्रिगर करता है। इनपुट स्ट्रिंग समाप्त होने तक हमारी परीक्षण दोहन प्रक्रिया जारी है। यह 4 और 13 में एक और मैच पाता है।

तीसरा उदाहरण एक मैच खोजने में विफल रहता है क्योंकि क्वांटिफायर का अधिकारी है। इस स्थिति में, पूरे इनपुट स्ट्रिंग का सेवन किया जाता है। * +, ( कैसे? )

A .*+जितना संभव हो उतना उपभोग करेगा, और नए मैच खोजने के लिए पीछे नहीं हटेगा जब regex एक मैच खोजने में विफल रहता है। क्योंकि अधिकारिक रूप बैकट्रैकिंग का प्रदर्शन नहीं करता है, आप शायद इसके साथ कई उपयोग नहीं देखेंगे .*+, बल्कि चरित्र वर्गों या समान प्रतिबंधों के साथ account: [[:digit:]]*+ phone: [[:digit:]]*+:।

यह रेगेक्स मिलान में काफी तेजी ला सकता है, क्योंकि आप रेगेक्स इंजन को बता रहे हैं कि यह संभावित मेल पर कभी भी पीछे नहीं हटना चाहिए अगर कोई इनपुट मेल नहीं खाता है। (यदि आपको सभी मिलान कोड हाथ से लिखना होता है, तो यह putc(3)इनपुट चरित्र को 'पुश बैक' करने के लिए कभी उपयोग न करने के समान होगा। यह बहुत ही भोले कोड के समान होगा जिसे कोई पहले प्रयास पर लिख सकता है। रेगेक्स इंजन को छोड़कर। जिस तरह से पुश-बैक के एकल चरित्र से बेहतर है, वे सभी बैक को शून्य में रिवाइंड कर सकते हैं और फिर से प्रयास कर सकते हैं। :)

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

अभिव्यक्ति के अंत में "फू" को संतुष्ट करने के लिए कुछ भी नहीं छोड़ा। उन स्थितियों के लिए एक परिमाणी मात्रात्मक का उपयोग करें, जहाँ आप बिना किसी चीज़ के सभी को जब्त करना चाहते हैं ( मतलब बंद का मतलब क्या है ;); यह बेहतर होगा

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

बराबर लालची मात्रात्मक मामलों में जहां मैच तुरंत नहीं मिलता है।


2
मुझे संदेह है कि ऐसा कोई मामला नहीं है जहां एक अधिकारपूर्ण मात्रा का मिलान कुछ से मेल खाता हो जो एक लालची क्वांटिफायर नहीं करेगा। मेरा मानना ​​है कि निम्नलिखित यह साबित करता है: एक लालची क्वांटिफायर हमेशा जितना संभव हो उतना मेल खाता है, फिर अगर यह एक मैच नहीं मिल सकता है तो वापस आ जाता है। जितना संभव हो सके, उतनी मात्रा में मैच्योर क्वांटिफायर मैच से बाहर हो जाता है । इसलिए ऐसा कुछ हो सकता है कि एक लालची मात्रा-मापक से मेल खाता हो, जो एक अधिकारपूर्ण मात्रा-मापक नहीं होगा, लेकिन विपरीत नहीं, क्योंकि वे दोनों एक ही क्रम में "पेड़" की खोज करते हैं, अधिकार-युक्त मात्रा-सूचक अधिक आसानी से छोड़ देता है। ;)
वाइल्डकार्ड

2
पुष्टि की गई: "यही वह परमाणु समूह है और उसके पास मात्रात्मक मात्राएँ हैं: बैकट्रैकिंग को रोककर दक्षता।" regular-expressions.info से तो इस उत्तर में बयान "लेकिन संभावित गति अप से अधिक, यह आपको रेगेक्स लिखने दे सकता है जो आपको मैच करने की आवश्यकता है।" वास्तव में काफी सटीक नहीं है।
वाइल्डकार्ड

1
@Wildcard, टिप्पणियों के लिए धन्यवाद; यह बता सकता है कि मुझे एक उदाहरण के साथ आने में परेशानी क्यों हुई। हेहे।
१।

19

http://swtch.com/~rsc/regexp/regexp1.html

मुझे यकीन नहीं है कि यह इंटरनेट पर सबसे अच्छा स्पष्टीकरण है, लेकिन यह यथोचित रूप से अच्छी तरह से लिखा गया है और उचित रूप से विस्तृत है, और मैं इसे वापस आ रहा हूं। शायद आप इस पर एक नजर डालना चाहें।

यदि आप एक उच्च स्तरीय (कम विस्तृत विवरण) चाहते हैं, तो सरल नियमित अभिव्यक्तियों के लिए जैसे कि आप जिसको देख रहे हैं, एक नियमित अभिव्यक्ति इंजन बैकट्रैकिंग द्वारा काम करता है। अनिवार्य रूप से, यह स्ट्रिंग के एक हिस्से को चुनता है ("खाता है") और उस खंड के खिलाफ नियमित अभिव्यक्ति से मेल खाने की कोशिश करता है। अगर यह मेल खाता है, महान। यदि नहीं, तो इंजन स्ट्रिंग के खंड की अपनी पसंद को बदल देता है और उस खंड के खिलाफ regexp से मेल खाने की कोशिश करता है, और इसी तरह, जब तक कि यह हर संभव विकल्प की कोशिश नहीं करता।

इस प्रक्रिया को पुनरावर्ती रूप से उपयोग किया जाता है: एक दिए गए नियमित अभिव्यक्ति के साथ एक स्ट्रिंग से मेल खाने के अपने प्रयास में, इंजन नियमित अभिव्यक्ति को टुकड़ों में विभाजित करेगा और एल्गोरिथ्म को प्रत्येक टुकड़े पर व्यक्तिगत रूप से लागू करेगा।

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

  • एक लालची क्वांटिफायर इंजन को पूरे स्ट्रिंग (या कम से कम, उन सभी के साथ शुरू करने के लिए कहता है जो पहले से ही नियमित अभिव्यक्ति के पिछले भागों से मेल नहीं खाते हैं) और जांचें कि क्या यह regexp से मेल खाता है। यदि हां, तो महान; इंजन रेगेक्सपी के बाकी हिस्सों के साथ जारी रह सकता है। यदि नहीं, तो यह फिर से कोशिश करता है, लेकिन जाँच की जाने वाली स्ट्रिंग के खंड से एक वर्ण (पिछले एक) को ट्रिम कर रहा है। अगर वह काम नहीं करता है, तो यह किसी अन्य चरित्र को बंद कर देता है, आदि। एक लालची क्वांटिफायर सबसे लंबे समय से सबसे कम समय तक संभावित मैचों की जांच करता है।

  • एक अनिच्छुक क्वांटिफायर इंजन को स्ट्रिंग के सबसे कम संभव टुकड़े से शुरू करने के लिए कहता है। यदि यह मेल खाता है, तो इंजन जारी रह सकता है; यदि नहीं, तो यह जाँच की जा रही स्ट्रिंग के खंड में एक वर्ण जोड़ता है और यह कोशिश करता है, और इसी तरह जब तक यह एक मैच नहीं पाता है या पूरे स्ट्रिंग का उपयोग नहीं किया गया है। तो एक अनिच्छुक क्वांटिफायर सबसे छोटे से लेकर सबसे लंबे समय तक संभावित मैचों की जांच करता है।

  • पहले प्रयास पर एक लालची क्वांटिफायर की तरह एक शक्तिशाली क्वांटिफायर है: यह इंजन को पूरे स्ट्रिंग की जांच करके शुरू करने के लिए कहता है। अंतर यह है कि अगर यह काम नहीं करता है, तो अधिकारी के पास यह मात्रा रिपोर्ट करती है कि मैच सही और फिर विफल हो गया। इंजन स्ट्रिंग के खंड को नहीं देखता है, और यह किसी भी अधिक प्रयास नहीं करता है।

यही कारण है कि अधिकारपूर्ण क्वांटिफायर मैच आपके उदाहरण में विफल रहता है: .*+पूरे स्ट्रिंग के खिलाफ जांच हो जाती है, जो कि यह मेल खाता है, लेकिन फिर इंजन उसके fooबाद अतिरिक्त पात्रों की तलाश में जाता है - लेकिन निश्चित रूप से यह उन्हें नहीं मिलता है, क्योंकि आप स्ट्रिंग के अंत में पहले से ही। यदि यह एक लालची क्वांटिफायर था, तो यह बैक .*-टू- बैक और अगले-से-अंतिम चरित्र तक एकमात्र मैच बनाने की कोशिश करेगा , फिर तीसरे से अंतिम चरित्र तक, फिर चौथे से अंतिम चरित्र तक, जो केवल तब सफल होता है स्ट्रिंग के पहले भाग को "खाया" के fooबाद एक लेफ्ट है .*


1
यह एक उत्कृष्ट स्रोत है। मुझे स्टेट मशीन डायग्राम्स बहुत पसंद हैं। :)
रेगेक्स रूकी

@Regex Rookie: ख़ुशी है कि आप इसे पसंद करते हैं :) उस साइट को देखने के बाद, हालांकि, मुझे लगता है कि मुझे यह स्पष्ट करना चाहिए कि इसका उद्देश्य एक नियमित अभिव्यक्ति इंजन के वैकल्पिक कार्यान्वयन को बढ़ावा देना है। बैकट्रैकिंग एल्गोरिथ्म I (आंशिक रूप से) और अन्य उत्तरों का वर्णन धीमा तरीका है; यह वेब पेज में वर्णित NFA / DFA विचार से पूरी तरह से अलग एल्गोरिथ्म है। Backtracking को समझना आसान है, यही वजह है कि regexps आमतौर पर शुरुआती लोगों को समझाया जाता है।
डेविड जेड

@ डेविड ज़स्लावस्की: अच्छी व्याख्या। कोष्ठक में आपकी टिप्पणी "एक लालची मात्रा में इंजन पूरे स्ट्रिंग के साथ शुरू करने के लिए कहता है (या कम से कम, यह सभी जो पहले से ही नियमित अभिव्यक्ति के पिछले भागों से मेल नहीं खाते हैं)" महत्वपूर्ण हैं। वे अनिच्छुक और अधिकारपूर्ण मात्रात्मक को भी लागू करते हैं। यह आपकी व्याख्या के साथ संगत बनाता है कि क्या होता है जब हम अपने उदाहरण पैटर्न को "("। * फू ";" *। *? फू ", और"। *। + फू ") से (" फू। * "?" फू "* में बदलते हैं)। "; और" फू। * + ")।
जॉन बेंटले

वास्तव में, xfooxxxxxxfoo नियमित अभिव्यक्ति के सामान्य (कंप्यूटर विज्ञान अर्थ) में मेल खाता है। NFA एक ऐसा राज्य होगा जहां यह किसी भी पात्र के साथ आपस में टकराता है और फिर इसे लुभाने के लिए कूद सकता है। DFA उस NFA का सीधा अनुवाद होगा। यह 8 राज्यों में किया जा सकता है।
user4951

@JimThio हाँ, क्योंकि यह एक अधिकार प्राप्त मात्रात्मक नहीं है।
डेविड जेड

12

यहां मेरा सेल और इंडेक्स पदों का उपयोग किया गया है ( एक इंडेक्स से सेल को अलग करने के लिए यहां आरेख देखें )।

लालची - लालची क्वांटिफायर और पूरे रेगेक्स के लिए जितना संभव हो उतना मिलान करें। यदि कोई मेल नहीं है, तो लालची मात्रात्मक पर बैकट्रैक।

इनपुट स्ट्रिंग: xfooxxxxxxfoo
Regex:। * फू

उपरोक्त रेगेक्स के दो भाग हैं:
(i) '। *' और
(ii) 'फू'

नीचे दिए गए प्रत्येक चरण में दो भागों का विश्लेषण किया जाएगा। ब्रेस के भीतर 'पास' या 'फेल' मैच के लिए अतिरिक्त टिप्पणियां बताई गई हैं।

चरण 1:
(i)। * = Xfooxxxxxxfoo - PASS ('। *' एक लालची मात्रात्मक है और संपूर्ण इनपुट स्ट्रिंग का उपयोग करेगा)
(ii) foo = अनुक्रमणिका 13 के बाद मिलान करने के लिए कोई वर्ण नहीं बचा - FAIL
Match विफल।

चरण 2:
(i)। * = Xfooxxxxxxfo - PASS (लालच क्वांटिफ़ायर पर पीछे चल रहा है '। *')
(ii) foo = o - FAIL
Match विफल।

चरण 3:
(i)। * = Xfooxxxxxxf - PASS (लालच क्वांटिफायर पर पीछे चल रहा है '। *')
(ii) foo = oo - FAIL
Match विफल।

चरण 4:
(i)। * = Xfooxxxxxx - PASS (लालची क्वांटिफ़ायर पर बैकट्रैकिंग। '*')
(ii) foo = foo - PASS
रिपोर्ट MATCH।

परिणाम: 1 मैच (तों)
मुझे "xfooxxxxxxfoo" पाठ मिला, जो सूचकांक 0 पर शुरू हुआ और सूचकांक 13 पर समाप्त हुआ।

अनिच्छुक - अनिच्छुक क्वांटिफायर के लिए जितना संभव हो उतना कम मिलान करें और पूरे रेगेक्स से मिलान करें। यदि कोई मेल नहीं है, तो अनिच्छुक क्वांटिफायर में वर्ण जोड़ें।

इनपुट स्ट्रिंग: xfooxxxxxxfoo
Regex:। *? फू

उपरोक्त रेगेक्स के दो भाग हैं:
(i) '। *?' और
(ii) 'फू'

चरण 1:।
* = '' (रिक्त) - PASS (अनिच्छुक क्वांटिफायर के लिए जितना संभव हो उतना कम मिलान करें। *।?)? अनुक्रमणिका 0 होने पर 'एक मेल है।)
foo = xfo - विफल (सेल 0,1,2 - अर्थात सूचकांक के बीच) 0 और 3)
मैच विफल रहा।

चरण 2:।
* = x - PASS (अनिच्छुक क्वांटिफायर में वर्ण जोड़ें। *।? '? सेल 0' x 'होने का एक मेल है।)
foo = foo - PASS
रिपोर्ट MATCH।

चरण 3:।
* = '' (रिक्त) - PASS (अनिच्छुक क्वांटिफायर के लिए जितना संभव हो उतना कम मिलान करें। *।?)? सूचकांक 4 'होने' एक मेल है।)
फू = xxx - विफल (सेल 4,5,6 - यानी के बीच सूचकांक) 4 और 7)
मैच विफल रहा।

चरण 4:।
* = x - PASS (अनिच्छुक क्वांटिफायर में वर्ण जोड़ें। *? '? सेल 4.)
foo = xxx - FAIL (सेल 5,6,7 - अर्थात 5 और 8 के बीच का सूचकांक)
मिलान विफल रहा।

चरण 5:।
* = xx - PASS (अनिच्छुक क्वांटिफायर में वर्ण जोड़ें। *? '?' सेल 4 थ्रू 5.)
फू = xxx - विफल (सेल 6,7,8 - यानी 6 और 9 के बीच का सूचकांक)
मिलान विफल रहा।

चरण 6:।
* = xxx - PASS (अनिच्छुक क्वांटिफायर में वर्ण जोड़ें। *? '?' सेल 4 थ्रू 6.)
फू = xxx - विफल (सेल 7,8,9 - यानी 7 और 10 के बीच का सूचकांक)
मिलान विफल रहा।

चरण 7:।
* = xxxx - PASS (अनिच्छुक क्वांटिफायर में वर्ण जोड़ें। *? '?' सेल 4 थ्रू 7.)
foo = xxf - FAIL (सेल 8,9,10 - यानी 8 और 11 के बीच का सूचकांक)
मिलान विफल रहा।

चरण 8:।
* = xxxxx - PASS (अनिच्छुक क्वांटिफायर में वर्ण जोड़ें। *? '?' सेल 4 थ्रू 8.)
foo = xfo - फेल (सेल 9,10,11 - यानी 9 और 12 के बीच का सूचकांक)
मिलान विफल रहा।

चरण 9:।
* = xxxxxx - PASS (अनिच्छुक क्वांटिफायर में वर्ण जोड़ें। *। *? सेल 4 thru 9.)
foo = foo = PASS (सेल 10,11,12 - यानी 10 और 13 के बीच का सूचकांक)
रिपोर्ट MATCH

चरण 10:।
* = '' (रिक्त) - PASS (अनिच्छुक क्वांटिफायर के लिए जितना संभव हो उतना कम मिलान करें '। *?); 13) रिक्त है।)
foo = मैच के लिए कोई वर्ण नहीं बचा है - फेल (
मिलान करने के लिए सूचकांक 13 के बाद कुछ भी नहीं है) अनुत्तीर्ण होना।

परिणाम: 2 मैच (तों)
मुझे "xfoo" पाठ मिला, जो सूचकांक 0 पर शुरू हुआ और सूचकांक 4 पर समाप्त हुआ।
मुझे "xxxxxxfoo" पाठ 4 सूचकांक पर शुरू हुआ और सूचकांक 13 पर समाप्त हुआ।

Possessive - जितना संभव हो सके उतने क्वांटिफायर से मिलान करें और पूरे रेगेक्स से मिलान करें। पीछे मत हटो।

इनपुट स्ट्रिंग: xfooxxxxxxfoo
Regex:। * + Foo

उपरोक्त रेगेक्स के दो भाग हैं: '। * +' और 'फू'।

चरण 1:
। * + = Xfooxxxxxxfoo - पास ( '। *' मैच अधिकार परिमाणक के लिए संभव के रूप में ज्यादा के रूप में)
foo = नहीं चरित्र से मेल करने के लिए छोड़ दिया - असफल (कुछ भी नहीं सूचकांक 13 के बाद मैच के लिए)
मैच में विफल रहे।

नोट: Backtracking की अनुमति नहीं है।

परिणाम: 0 मैच (तों)


1

लालची: "पात्रों के सबसे लंबे संभव अनुक्रम से मेल खाते हैं"

अनिच्छुक: "पात्रों के सबसे कम संभव अनुक्रम से मेल खाते हैं"

संभावित: यह थोड़ा अजीब है क्योंकि यह नहीं है (लालची और अनिच्छुक के विपरीत) पूरे रेगेक्स के लिए एक मैच खोजने की कोशिश करें।

वैसे: कोई रेगेक्स पैटर्न मैचर कार्यान्वयन कभी बैकट्रैकिंग का उपयोग नहीं करेगा। सभी वास्तविक जीवन के पैटर्न मिलान बहुत तेज हैं - नियमित अभिव्यक्ति की जटिलता से लगभग स्वतंत्र हैं!


जहाँ तक मुझे पता है कि अधिकांश सामान्य उपयोग कार्यान्वयन अब सुविधाओं से भरे हुए हैं इसलिए बैकट्रैकिंग का उपयोग नहीं करना असंभव हो गया। इसलिए सिद्धांत रूप में उन्हें कुछ मामलों के लिए बेहद (घातीय) धीमा होना चाहिए। लेकिन उन मामलों में से अधिकांश के लिए पैटर्न मिलानकर्ता में निर्मित विशेष अनुकूलन हैं।
रॉबर्ट

0

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

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

वर्णों का प्रवाह सक्रिय अनुक्रम से संगरोध में होता है। परिणामी व्यवहार यह है कि जितना संभव हो उतना मूल अनुक्रम एक मैच में शामिल किया गया है।

अनिच्छुक परिमाणीकरण ज्यादातर लालची योग्यता के समान है, सिवाय इसके कि पात्रों का प्रवाह विपरीत है - अर्थात, वे संगरोध में शुरू होते हैं और सक्रिय अनुक्रम में प्रवाह करते हैं । परिणामी व्यवहार यह है कि मूल अनुक्रम में से कम से कम एक मैच में शामिल किया गया है।

पॉजेसिव क्वांटिफिकेशन में संगरोध नहीं होता है और एक निश्चित सक्रिय अनुक्रम में सब कुछ शामिल होता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.