2013-05-19 6 views
6

मेरे पास एक .NET regex है जिसे मैं विंडोज पावरहेल का उपयोग कर परीक्षण कर रहा हूं। उत्पादन इस प्रकार है:गैर लालची रेगेक्स क्वांटिफायर लालची परिणाम देता है

> [System.Text.RegularExpressions.Regex]::Match("aaa aaa bbb", "aaa.*?bbb") 


Groups : {aaa aaa bbb} 
Success : True 
Captures : {aaa aaa bbb} 
Index : 0 
Length : 11 
Value : aaa aaa bbb 

मेरे उम्मीद थी कि ? परिमाणक का उपयोग कर मैच aaa bbb होने के लिए कारण होगा, के रूप में एक के के दूसरे समूह अभिव्यक्ति को पूरा करने के लिए पर्याप्त है। क्या गैर लालची क्वांटिफायरों की मेरी समझ त्रुटिपूर्ण है, या क्या मैं गलत तरीके से परीक्षण कर रहा हूं?

नोट:

regex: aaa.*?bbb 
result: aaa aaa bbb 

regex: aaa.*bbb 
result: aaa aaa bbb bbb 

regex इंजन aaa की पहली आवृत्ति पाता है और फिर छोड़ देता है तो सभी वर्णों (.*?): इस स्पष्ट रूप से नहीं के रूप में Regular Expression nongreedy is greedy

उत्तर

5

यह एक आम गलतफहमी है। आलसी क्वांटिफायर कम से कम संभव मैच की गारंटी नहीं देते हैं। वे केवल यह सुनिश्चित करते हैं कि वर्तमान स्थिति से वर्तमान क्वांटिफायर, समग्र मिलान के लिए आवश्यकतानुसार अधिक वर्णों से मेल नहीं खाता है।

यदि आप वास्तव में सबसे कम संभव मैच सुनिश्चित करना चाहते हैं, तो आपको यह स्पष्ट करने की आवश्यकता है। इस मामले में, इसका मतलब है कि .*? के बजाय, आप एक सब्रेगेक्स चाहते हैं जो किसी भी चीज़ से मेल नहीं खाता जो न तो aaa और न ही bbb है। परिणामस्वरूप रेगेक्स

aaa(?:(?!aaa|bbb).)*bbb 
+0

मैंने अभी किया जो मैंने पहले किया था, और फ्रेडल के प्रासंगिक अध्याय से परामर्श किया। इससे मुझे 'aaa ((?! Aaa)। * * बीबीबी', जो आपने कहा था उतना ही कम है, सिवाय इसके कि आपके उत्तर में उप-कैप्चरिंग गैर-कैप्चरिंग बनाने और नकारात्मक में बीबीबी के लिए परीक्षण करने के अतिरिक्त विवरण हैं भविष्य का ध्यान करना। अच्छा उत्तर। –

5

एक ही समस्या स्ट्रिंग aaa aaa bbb bbb के लिए परिणाम की तुलना है पहलेbbb की घटना, लेकिन लालची ऑपरेटर (.*) के लिए यह एक बड़ा परिणाम खोजने के लिए आगे बढ़ेगा और इसलिए लास से मेल खाता है टीbbb की घटना।

+0

यह हो रहा है कि यह क्या हो रहा है की स्पष्ट व्याख्या है। +1 – duozmo

0

खैर यह वास्तव में सरल है, हम निम्न स्ट्रिंग

aaa aaa bbb

देखते हैं कि हम इस regex aaa.*?bbb करते है है। regex इंजन aaa

aaa aaa bbb

regex इंजन अब .*?bbb है के साथ शुरू होगा। यह space

aaa अंतरिक्ष aaa bbb

के साथ आगे बढ़ना होगा लेकिन हम अभी भी bbb जब तक कुछ अक्षर है? तो regex इंजन यह तरीका है जारी रखने के लिए और एक

aaa aaa अंतरिक्ष bbb

के दूसरे सेट से मेल खाएगी अंत में regex इंजन से मेल खाएगी bbb:

aaa aaa बीबीबी


तो चलो देखते हैं, अगर हम केवल दूसरे aaa हम निम्नलिखित regex का उपयोग कर सकता है मिलान करना चाहते हैं:

(?<!^)aaa.*?bbb, इस aaa उस वाक्य की शुरुआत में नहीं है मैच के लिए मायने रखता है।

हम aaa(?= bbb).*?bbb का भी उपयोग कर सकते हैं, इसका मतलब aaa से मेल खाता है जिसके बाद space bbb है। 2 -

यह 1 काम कर देखें।

बस मेरी इंद्रियों पर आया, लेकिन आप सीधे aaa bbb का उपयोग क्यों नहीं करते?

1

यह लालची/आलसी समस्या नहीं है। समस्या इस तथ्य के लिए आती है कि आपकी स्ट्रिंग का विश्लेषण बाएं से दाएं से किया जाता है। जब पहला aaa मिलान किया जाता है, तो रेगेक्स इंजन पूर्ण पैटर्न रखने के लिए वर्णों को एक-एक करके जोड़ता है।

ध्यान दें कि एक लालची व्यवहार के साथ, आप एक ही परिणाम प्राप्त करते हैं: पहला aaa मिलान किया जाता है, रेगेक्स इंजन पूरे मैच होने तक चरित्र द्वारा सभी अंतिम पात्रों और बैकट्रैक चरित्र को लेता है।

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