2011-11-13 18 views
13

मुझे दिए गए रेगेक्स के लिए स्ट्रिंग में सभी मैचों को खोजने की ज़रूरत है। मैं ऐसा करने के लिए findall() का उपयोग कर रहा हूं जब तक कि मैं ऐसे मामले में नहीं आया जहां यह मेरी अपेक्षा नहीं कर रहा था।पायथन - regex खोज और findall

regex = re.compile('(\d+,?)+') 
s = 'There are 9,000,000 bicycles in Beijing.' 

print re.search(regex, s).group(0) 
> 9,000,000 

print re.findall(regex, s) 
> ['000'] 

इस मामले search() रिटर्न मैं क्या जरूरत है (सबसे लंबे समय तक मैच), लेकिन findall() अलग ढंग से व्यवहार करती है, हालांकि डॉक्स मतलब यह एक ही होना चाहिए में:

findall() मैचों में एक की सभी घटनाओं उदाहरण के लिए पैटर्न, न केवल search() करता है।

  • क्यों व्यवहार अलग है?

  • search() के साथ findall() (या कुछ और) के परिणाम को मैं कैसे प्राप्त कर सकता हूं?

+0

'' ([\ d,] +) ' – dawg

उत्तर

15

ठीक है, मैं देख रहा हूँ क्या हो रहा है ... डॉक्स से:

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

यह पता चला है के रूप में, आप एक समूह, "(\ d + ,?)" ... हां, तो क्या यह लौटने है इस समूह के पिछले घटना, या 000

एक समाधान है की क्या ज़रूरत है , तो एक समूह द्वारा पूरे regex के चारों ओर इस

regex = re.compile('((\d+,?)+)') 

की तरह है, यह [('9,000,000', '000')], जो दोनों का मिलान नहीं हुआ समूहों युक्त एक टपल है वापस आ जाएगी। बेशक, आप केवल पहले के बारे में परवाह करते हैं।

व्यक्तिगत रूप से, मैं निम्नलिखित regex

regex = re.compile('((\d+,)*\d+)') 

का प्रयोग करेंगे सामान मिलान से बचने के लिए की तरह

संपादित करें "यह एक बुरा संख्या 9123 है,"।

यहाँ एक तरह से कोष्ठक द्वारा अभिव्यक्ति के चारों ओर या tuples

s = "..." 
regex = re.compile('(\d+,?)+') 
it = re.finditer(regex, s) 

for match in it: 
    print match.group(0) 

finditer पुनरावर्तक है कि आप सभी मिलान न मिलने तक पहुँचने के लिए उपयोग कर सकते हैं रिटर्न से निपटने के लिए होने से बचाने के लिए है। ये मिलान ऑब्जेक्ट वही हैं जो re.search देता है, इसलिए समूह (0) आपके द्वारा अपेक्षित परिणाम देता है।

+0

स्पष्टीकरण के लिए धन्यवाद। यह पता चला है कि 'खोजकर्ता' वास्तव में आपके द्वारा सुझाए गए कार्यों के अनुरूप बेहतर था। रेगेक्स उपयोगकर्ता इनपुट से आता है इसलिए मेरे पास इसका नियंत्रण नहीं है। – armandino

7

@ aleph_null का answer सही ढंग से बताता है कि आपकी समस्या का कारण क्या है, लेकिन मुझे लगता है कि मेरे पास एक बेहतर समाधान है।यह regex का उपयोग करें:

regex = re.compile(r'\d+(?:,\d+)*') 

कुछ कारण जिनकी वजह यह बेहतर है:

  1. (?:...), एक गैर पर कब्जा समूह है ताकि आप केवल प्रत्येक मैच के लिए एक परिणाम मिलता है।

  2. \d+(?:,\d+)* एक बेहतर रेगेक्स, अधिक कुशल और झूठी सकारात्मक वापसी की संभावना कम है।

  3. यदि संभव हो तो आपको हमेशा पाइथन के कच्चे तारों का उपयोग रेगेक्स के लिए करना चाहिए; आप कम regex भागने दृश्यों से हैरान किया जाए स्ट्रिंग-शाब्दिक भागने दृश्यों के रूप में व्याख्या की जा रही है (जैसे \bके लिए बैकस्पेस) (जैसे \bशब्द सीमा के लिए)।

+0

धन्यवाद एलन! मुझे पहले उल्लेख किया जाना चाहिए था लेकिन मेरे पास regex पर नियंत्रण नहीं है क्योंकि यह उपयोगकर्ता इनपुट है .. – armandino

+2

कोई समस्या नहीं! लेकिन, रिकॉर्ड के लिए, उपयोगकर्ताओं को आपके ऐप द्वारा इनपुट रेजेक्स को निष्पादित करने देना एक बुरा विचार है। जब उनकी बुरी तरह लिखित (या बस जल्दी से टाइप की गई) regexes मिलान करने में विफल रहता है, या सिस्टम को दुर्घटनाग्रस्त हो जाता है, तो वे इसके लिए * आप * को दोष देने जा रहे हैं। ;) –

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