2012-01-26 13 views
5

मैं कुछ डॉकस्ट्रिंग को पार्स करने की कोशिश कर रहा हूं।regex: वैकल्पिक भागों के साथ स्ट्रिंग

एक उदाहरण docstrings है:

Test if a column field is larger than a given value 
    This function can also be called as an operator using the '>' syntax 

    Arguments: 
     - DbColumn self 
     - string or float value: the value to compare to 
      in case of string: lexicographic comparison 
      in case of float: numeric comparison 
    Returns: 
     DbWhere object 

दोनों Arguments और Returns भागों वैकल्पिक हैं। मैं चाहता हूं कि मेरा रेगेक्स समूह के रूप में विवरण (पहली पंक्तियां), Arguments भाग (यदि मौजूद है) और Returns भाग (यदि मौजूद है) के रूप में वापस लौटना चाहता है।

regex मैं अब है:

m = re.search('(.*)(Arguments:.*)(Returns:.*)', s, re.DOTALL) 

और मामले में काम करता है सभी तीन भागों मौजूद हैं लेकिन जैसे ही Arguments के रूप में विफल रहता है या Returns भागों उपलब्ध नहीं हैं। मैंने ?? जैसे गैर-लालची संशोधक के साथ कई भिन्नताओं की कोशिश की है लेकिन इसका कोई फायदा नहीं हुआ है।

संपादित करें:Arguments और Returns भागों मौजूद हैं, मैं वास्तव में केवल Arguments: और Returns: क्रमशः के बाद पाठ से मेल करना चाहते हैं।

धन्यवाद!

+1

क्या ऑर्डर हमेशा तय किया गया है? I. ई।, मानक पाठ के बाद और 'रिटर्न' से पहले हमेशा 'तर्क' है? –

+0

हां, आदेश हमेशा तय किया जाता है। – BioGeek

उत्तर

7

कोशिश के साथ:

re.search('^(.*?)(Arguments:.*?)?(Returns:.*)?$', s, re.DOTALL) 

बस एक ? जोड़कर, और गैर लालची द्वारा (फिर से) पहले दो समूहों के क्वालिफायर बनाकर दूसरे और तीसरे समूह वैकल्पिक बनाने एक ? जोड़कर उन पर (हाँ, उलझन में)।

इसके अलावा, यदि आप पैटर्न के पहले समूह पर गैर-लालची संशोधक का उपयोग करते हैं, तो यह सबसे कम संभव सबस्ट्रिंग से मेल खाएगा, जो .* खाली स्ट्रिंग है। पैटर्न के अंत में आप अंतराल के चरित्र ($) जोड़कर इसे दूर कर सकते हैं, जो पहले समूह को पैटर्न को संतुष्ट करने के लिए जितना संभव हो उतना पात्र मिलान करने के लिए मजबूर करता है, यानी Arguments और कोई नहीं होने पर पूरी स्ट्रिंग Returns अनुभाग, और मौजूद होने पर उन वर्गों से पहले सबकुछ।

संपादित करें: ठीक है, अगर आप सिर्फArguments: और Returns: टोकन के बाद पाठ कैप्चर करना चाहते हैं, तो आप कुछ और समूहों में टक करना होगा। आप मेल करना चाहते हैं

>>> m = re.search('^(?P<description>.*?)(Arguments:(?P<arguments>.*?))?(Returns:(?P<returns>.*))?$', s, re.DOTALL) 
>>> m.groupdict()['description'] 
"Test if a column field is larger than a given value\n This function can also be called as an operator using the '>' syntax\n\n " 
>>> m.groupdict()['arguments'] 
'\n  - DbColumn self\n  - string or float value: the value to compare to\n   in case of string: lexicographic comparison\n   in case of float: numeric comparison\n ' 
>>> m.groupdict()['returns'] 
'\n  DbWhere object' 
>>> 
+0

एक आकर्षण की तरह काम करता है! यदि आप वैकल्पिक भागों के लिए, केवल 'तर्क' और 'रिटर्न' के बाद पाठ से मिलान करना चाहते हैं, तो आप रेगेक्स को कैसे संशोधित करेंगे? – BioGeek

+0

कुछ 're.search ('^(। *?) (तर्क: (। *?)) (रिटर्न: (। *))? $ ', डॉक्टर, पुनः। डॉटल)' काम करता है, लेकिन मैं नहीं करता ' दूसरे और चौथे समूह के लिए यह ख्याल नहीं है। – BioGeek

+0

मैंने अपना जवाब संपादित कर लिया है। बस समूहों का नाम दें और 'समूह() 'के बारे में भूल जाएं, इसके बजाय' groupdict()' का उपयोग करें। – Chewie

3

: समझ बनाने के लिए शुरू कर रहा है - हम नहीं सभी समूहों को उपयोग करने के लिए (अरे एक और प्रश्न चिह्न,!) जा रहे हैं, इसलिए उन्हें -साथ <?P<name> अंकन नामकरण वैकल्पिक Arguments: और Returns: अनुभाग, और के बाद पाठ आप अपने कैप्चर समूहों को नाम देने के लिए (?P<name>...) का उपयोग नहीं करना चाहते हैं, तो आप (?:...), नियमित ब्रांड्स के गैर-कैप्चरिंग संस्करण का भी उपयोग कर सकते हैं।

regex इस प्रकार दिखाई देगा:

m = re.search('^(.*?)(?:Arguments:(.*?))?(?:Returns:(.*?))?$', doc, re.DOTALL) 
#      ^^     ^^ 

python3 documentation के अनुसार:

(?:...)

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

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