2010-04-26 9 views
16

एक (अन्यथा काफी शक्तिशाली) re अजगर में मॉड्यूल के विशेष मोड़ उदाहरण के लिए, कि re.split()will never split a string on a zero-length match है अगर मैं शब्द सीमाओं के साथ एक स्ट्रिंग विभाजित करना चाहते हैं:पायथन की 're.split()' शून्य-लंबाई वाले मैचों पर क्यों विभाजित नहीं है?

>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!") 
['Split', 'along', 'words,', 'preserve', 'punctuation!'] 
बजाय

['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!'] 

यह सीमा क्यों है? क्या यह डिजाइन द्वारा है? क्या अन्य रेगेक्स स्वाद इस तरह व्यवहार करते हैं?

उत्तर

22

यह एक डिज़ाइन निर्णय है जो बनाया गया था, और किसी भी तरह से चला सकता था। टिम पीटर्स this post बनाया व्याख्या करने के लिए:

उदाहरण के लिए, यदि आप पैटर्न x * द्वारा "abc" विभाजित है, आप क्या उम्मीद करते हैं? पैटर्न 4 स्थानों, में (लंबाई 0) के साथ मेल खाता है, लेकिन मुझे यकीन है कि ज्यादातर लोगों को पाने के लिए

आश्चर्य होगा [ ',' एक ',' बी ',' सी ',' ']

के बजाय (के रूप में वे मिलता है)

[ 'एबीसी'] वापस

कुछ दूसरों यद्यपि उसके साथ सहमत नहीं हैं। पिछली संगतता के मुद्दों के कारण Guido van Rossum doesn't want it changed। उन्होंने say:

हालांकि मैं इस व्यवहार को सक्षम करने के लिए ध्वज जोड़ने के साथ ठीक हूं।

संपादित:

एक workaround जनवरी Burgy द्वारा पोस्ट की गई है:

>>> s = "Split along words, preserve punctuation!" 
>>> re.sub(r"\s+|\b", '\f', s).split('\f') 
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!'] 

कहाँ '\f' किसी भी अप्रयुक्त चरित्र द्वारा प्रतिस्थापित किया जा सकता है।

+0

लिंक के लिए और वैकल्पिक हल के लिए धन्यवाद। मुझे सच में लगता है कि उन्हें बीडीएफएल के सुझाव को लेना चाहिए और इसके लिए एक झंडा जोड़ना चाहिए। –

+0

यह वास्तव में लंगड़ा डिजाइन निर्णय है। आरईएस एक ऐसी चीज है जहां डिजाइन निर्णय निर्णय लेने वाले लोगों द्वारा संचालित नहीं किए जाने चाहिए क्योंकि आरईएस के बारे में कई चीजें लोगों की अपेक्षाओं के अनुरूप नहीं हैं, जो कुछ भी इसका मतलब है। 'x *' 'abc' से मेल खाना चाहिए क्योंकि आरई कहता है: "एक्स, शून्य या अधिक बार मैच करें"। जब आप '*' का उपयोग करते हैं तो आपको यही मिलता है। –

+0

एक पास्कल केस वैरिएबल नाम ('re.split (' (? <= [A-z]) (? = [ए-जेड]) ',? = ए-जेड])', नाम) को विभाजित करने का प्रयास करते समय बस इस समस्या में भाग गया। ')। बहुत बुरा। – Blixt

0

मूल रूप से, विभाजित() एक में दो अलग-अलग कार्य होते हैं। यदि आप पैरामीटर प्रदान करते हैं, तो यह बिना किसी कॉल किए जाने से बहुत अलग व्यवहार करता है।

सबसे पहले, ऐसा लगता है कि होगा

s.split() == s.split(' \t\n') 

लेकिन इस मामले, जैसा कि आप से पता चला है नहीं है। दस्तावेज़ का कहना है:

[...] सितम्बर तय नहीं है तो या कोई नहीं है, कोई श्वेत रिक्ति स्ट्रिंग एक विभाजक है और रिक्त स्ट्रिंग परिणाम से हटा दिया जाता है। [...]

यहां तक ​​कि 'remove_empty' पैरामीटर जोड़ना भी यह अजीब व्यवहार करेगा, क्योंकि 'remove_empty' का डिफ़ॉल्ट 'sep' पैरामीटर पर निर्भर करता है।

+0

मुझे लगता है कि आपको गलत '.plit() 'मिला है - मैं' re.split() 'का जिक्र कर रहा था, स्ट्रिंग विधि नहीं। –

+0

आह, ज़ाहिर है :-) –

1

इस समस्या को वैकल्पिक हल के लिए आप regex package बनाता है, जिनमें से VERSION1 मोड का उपयोग कर सकते हैं split()उत्पादन शून्य लंबाई के साथ-साथ मेल खाता है:

>>> import regex as re 
>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!", flags=re.V1) 
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!'] 
संबंधित मुद्दे