2013-01-06 13 views
7

मैं पायथन रेगेक्स का उपयोग कर एक छोटी सी समस्या में भाग गया।वैकल्पिक ऑपरेटर के साथ एकाधिक regex पैटर्न मिलान?

मान लीजिए इस इनपुट है:

(zyx)bc 

क्या मैं, प्राप्त करने के लिए प्राप्त कर रहा है जो कुछ भी एक भी मैच के रूप में कोष्ठकों के बीच है कोशिश कर रहा हूँ और एक व्यक्ति के रूप में मैच से बाहर किसी भी वर्ण। वांछित परिणाम लाइनों के साथ होगा:

['zyx','b','c'] 

मैचों का क्रम रखा जाना चाहिए।

मैंने इसे पायथन 3.3 के साथ प्राप्त करने का प्रयास किया है, लेकिन सही रेगेक्स को समझने के लिए प्रतीत नहीं होता है। अब तक मेरे पास है:

matches = findall(r'\((.*?)\)|\w', '(zyx)bc') 

print(matches) पैदावार निम्नलिखित:

['zyx','',''] 

कोई भी विचार मैं गलत क्या कर रहा हूँ?

+0

क्यों न सिर्फ 'xyz | एक | b'? – fge

+0

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

उत्तर

11

re.findall के प्रलेखन से:

एक या अधिक समूहों पैटर्न में मौजूद हैं, समूहों की एक सूची प्रदान; यदि पैटर्न में एक से अधिक समूह हैं तो यह tuples की एक सूची होगी।

जबकि आपका regexp तीन बार स्ट्रिंग से मेल खाता है, (.*?) समूह दूसरे दो मैचों के लिए खाली है। वैकल्पिक रूप से

>>> re.findall(r'\((.*?)\)|(\w)', '(zyx)bc') 
[('zyx', ''), ('', 'b'), ('', 'c')] 

, आप सभी समूहों को निकालने सकता है फिर से तार की एक सरल सूची प्राप्त करने के लिए: आप regexp का दूसरा भाग के उत्पादन में चाहते हैं, आप एक दूसरे समूह में जोड़ सकते हैं

>>> re.findall(r'\(.*?\)|\w', '(zyx)bc') 
['(zyx)', 'b', 'c'] 

हालांकि आपको मैन्युअल रूप से कोष्ठक को हटाने की आवश्यकता होगी।

+0

एफवाईआई: उत्तर के लिए धन्यवाद। कोष्ठक को हटाने के लिए: 'match = [match.strip ('() ') findall में मिलान के लिए (आर' \ (। *? \) | \ W ', case)]' –

1

डॉक्स विशेष समूहों के इलाज का उल्लेख है, तो parenthesized पैटर्न के चारों ओर एक समूह नहीं रख सकता हूं, और तुम सब कुछ मिल जाएगा, लेकिन आप मिलान किया डेटा अपने आप से कोष्ठक को दूर करने की आवश्यकता होगी:

>>> re.findall(r'\(.+?\)|\w', '(zyx)bc') 
['(zyx)', 'b', 'c'] 

या का उपयोग अधिक समूहों, फिर परिणामी tuples की प्रक्रिया तार आप की तलाश प्राप्त करने के लिए:

>>> [''.join(t) for t in re.findall(r'\((.+?)\)|(\w)', '(zyx)bc')] 
>>> ['zyx', 'b', 'c'] 
1
In [108]: strs="(zyx)bc" 

In [109]: re.findall(r"\(\w+\)|\w",strs) 
Out[109]: ['(zyx)', 'b', 'c'] 

In [110]: [x.strip("()") for x in re.findall(r"\(\w+\)|\w",strs)] 
Out[110]: ['zyx', 'b', 'c'] 
2

चलो re.DEBUG का उपयोग कर हमारे उत्पादन पर एक नज़र डालें।

branch 
    literal 40 
    subpattern 1 
    min_repeat 0 65535 
     any None 
    literal 41 
or 
    in 
    category category_word 

आउच, वहाँ वहाँ में केवल एक ही है, लेकिन subpatternre.findall केवल यदि मौजूद subpattern रों बाहर खींचती है!

a = re.findall(r'\((.*?)\)|(.)', '(zyx)bc',re.DEBUG); a 
[('zyx', ''), ('', 'b'), ('', 'c')] 
branch 
    literal 40 
    subpattern 1 
    min_repeat 0 65535 
     any None 
    literal 41 
or 
    subpattern 2 
    any None 

बेहतर। :)

अब हमें इसे अपने इच्छित स्वरूप में बनाना है।

[i[0] if i[0] != '' else i[1] for i in a] 
['zyx', 'b', 'c'] 
1

अन्य उत्तरों आपको दिखाए गए परिणाम को कैसे प्राप्त करें, लेकिन मैन्युअल रूप से कोष्ठक को हटाने के अतिरिक्त चरण के साथ। आप अपने regex में lookarounds का उपयोग करते हैं, तो आप मैन्युअल कोष्ठकों पट्टी की जरूरत नहीं होगी:

>>> import re 
>>> s = '(zyx)bc' 
>>> print (re.findall(r'(?<=\()\w+(?=\))|\w', s)) 
['zyx', 'b', 'c'] 

व्याख्या:

(?<=\() // lookbehind for left parenthesis 
\w+  // all characters until: 
(?=\)) // lookahead for right parenthesis 
|  // OR 
\w  // any character 
संबंधित मुद्दे