2017-08-15 13 views
13

मैं पाइथन में टेक्स्ट से संख्याओं और कुछ अन्य चीजों को विभाजित करने के लिए एक फ़ंक्शन लिख रहा हूं। कोड इस तरह दिखता है:पायथन 2 और 3 're.sub' असंगतता

EN_EXTRACT_REGEX = '([a-zA-Z]+)' 
NUM_EXTRACT_REGEX = '([0-9]+)' 
AGGR_REGEX = EN_EXTRACT_REGEX + '|' + NUM_EXTRACT_REGEX 

entry = re.sub(AGGR_REGEX, r' \1\2', entry) 

अब, यह कोड python3 में पूरी तरह से ठीक काम करता है, लेकिन यह को Python2 के तहत काम नहीं करता है और एक "बेजोड़ समूह" त्रुटि मिलती है।

समस्या यह है कि मुझे दोनों संस्करणों का समर्थन करने की आवश्यकता है, और मैं इसे python2 में ठीक से काम नहीं कर सका, हालांकि मैंने कई अन्य तरीकों की कोशिश की।

मुझे उत्सुकता है कि इस समस्या की जड़ क्या हो सकती है, और इसके लिए कोई कामकाज है?

उत्तर

10

मुझे लगता है कि समस्या हो सकती है कि कि regex पैटर्न एक या subpatterns EN_EXTRACT_REGEX और NUM_EXTRACT_REGEX, लेकिन दोनों नहीं के अन्य मेल खाता है।

जब re.sub() पहले पैटर्न में अल्फा वर्णों से मेल खाता है तो यह \2 के साथ दूसरे समूह संदर्भ को प्रतिस्थापित करने का प्रयास करता है जो विफल रहता है क्योंकि केवल पहला समूह मेल खाता है - कोई दूसरा समूह नहीं है।

इसी प्रकार जब अंक पैटर्न मिलान किया जाता है तो वहां \1 समूह विकल्प नहीं है और इसलिए यह भी विफल हो जाता है।

आप देख सकते हैं कि इस अजगर 2 में इस परीक्षण के साथ मामला है:

>>> re.sub(AGGR_REGEX, r' \1', 'abcd') # reference first pattern 
abcd 
>>> re.sub(AGGR_REGEX, r' \2', 'abcd') # reference second pattern 
Traceback (most recent call last): 
.... 
sre_constants.error: unmatched group 

अंतर अजगर 2 और अजगर 3. के लिए regex इंजन के विभिन्न संस्करणों के भीतर स्थित दुर्भाग्य से मैं प्रदान नहीं कर सकते चाहिए

संस्करण 3.5 में परिवर्तित:: बेजोड़ समूहों कोई रिक्त स्ट्रिंग से बदला जाता है अंतर के लिए एक निश्चित कारण, तथापि, वहाँ एक दस्तावेज बेजोड़ समूहों के बारे में re.sub() के लिए संस्करण 3.5 में परिवर्तन है।

जो बताता है कि यह पायथन> = 3.5 में क्यों काम करता है लेकिन पिछले संस्करणों में नहीं: बेजोड़ समूहों को मूल रूप से अनदेखा किया जाता है।


एक समाधान आप एक ही समूह के रूप में दोनों मैचों को संभालने के लिए अपने पैटर्न को बदल सकते हैं के रूप में:

import re 

EN_EXTRACT_REGEX = '[a-zA-Z]+' 
NUM_EXTRACT_REGEX = '[0-9]+' 
AGGR_REGEX = '(' + EN_EXTRACT_REGEX + '|' + NUM_EXTRACT_REGEX + ')' 
# ([a-zA-Z]+|[0-9]+) 

for s in '', '1234', 'abcd', 'a1b2c3', 'aa__bb__1122cdef', '_**_': 
    print(re.sub(AGGR_REGEX, r' \1', s)) 

आउटपुट

 

1234 
abcd 
a 1 b 2 c 3 
aa__ bb__ 1122 cdef 
_**_ 
+0

धन्यवाद, यह दोनों संस्करणों पर अच्छी तरह से काम करता है। :) –

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