2008-09-24 15 views
20

क्या यह निर्धारित करने का कोई तरीका है कि किसी नियमित नियमित अभिव्यक्ति में कितने कैप्चर समूह हैं?पायथन नियमित अभिव्यक्तियों में कैप्चर समूहों की संख्या जानें

मैं follwing ऐसा करने में सक्षम होना चाहते हैं:

def groups(regexp, s): 
    """ Returns the first result of re.findall, or an empty default 

    >>> groups(r'(\d)(\d)(\d)', '123') 
    ('1', '2', '3') 
    >>> groups(r'(\d)(\d)(\d)', 'abc') 
    ('', '', '') 
    """ 
    import re 
    m = re.search(regexp, s) 
    if m: 
     return m.groups() 
    return ('',) * num_of_groups(regexp) 

यह मेरे जैसे सामान करने के लिए अनुमति देता है:

first, last, phone = groups(r'(\w+) (\w+) ([\d\-]+)', 'John Doe 555-3456') 

हालांकि, मैं num_of_groups लागू करने के लिए कैसे पता नहीं है। (वर्तमान में मैं सिर्फ उसके चारों ओर काम करते हैं।)

संपादित करें:advice from rslite के बाद, मैं re.search साथ re.findall बदल दिया।

sre_parse सबसे मजबूत और व्यापक समाधान की तरह लगता है, लेकिन पेड़ के ट्रैवर्सल की आवश्यकता है और यह थोड़ा भारी प्रतीत होता है।

मिज़र्डएक्स की नियमित अभिव्यक्ति सभी अड्डों को कवर करने लगती है, इसलिए मैं इसके साथ जा रहा हूं।

उत्तर

29
def num_groups(regex): 
    return re.compile(regex).groups 
+5

यह वास्तव में समूहों की संख्या वापस नहीं करेगा, यह सभी समूहों का एक टुपल लौटाएगा। समूहों की संख्या वापस करने के लिए, आपको निम्न कोड (पायथन 3.4 में) की आवश्यकता होगी: 'रिटर्न लेन (re.compile (regex)। समूह()) ' –

+2

@RaziShaban' re.compile (regex)। समूह '' int' प्रकार की संपत्ति है। 're.compile (regex) .match (इनपुट)। समूह()' एक विधि है, जो 'tuple' लौटा रहा है। –

+0

सही, क्षमा करें, मैं खोज के साथ काम कर रहा था, संकलित नहीं। प्वाइंट मैं बना रहा था कि आपके फ़ंक्शन को 'num_groups' नाम दिया गया है लेकिन एक टुपल देता है, संख्या नहीं। –

1

सबसे पहले यदि आपको केवल re.findall के पहले परिणाम की आवश्यकता है, तो केवल पुन: खोज का उपयोग करना बेहतर होगा जो एक मैच या कोई नहीं देता है। ।

def num_of_groups(regexp): 
    rg = re.compile(r'(?<!\\)\(') 
    return len(rg.findall(regexp)) 

ध्यान दें कि यह नहीं करता है:

समूहों के लिए आप '(' उन है कि '\' की सहायता से निकले कर रहे हैं को छोड़कर आप उस के लिए एक और regex इस्तेमाल कर सकते हैं खुला कोष्ठक की संख्या की गणना कर सकता है नंबर काम करें यदि रेगेक्स में गैर-कैप्चरिंग समूह हैं और यदि '(' इसे '[(]' के रूप में उपयोग करके बच निकला है, तो यह बहुत विश्वसनीय नहीं है। लेकिन आपके द्वारा उपयोग किए जाने वाले रेगेक्स के आधार पर यह मदद कर सकता है।

2

lastindex मिलान ऑब्जेक्ट की संपत्ति आप जो खोज रहे हैं वह होनी चाहिए। re module docs देखें।

+0

तो कोई मुकाबला नहीं पाया जाता है, मैं एक मैच वस्तु नहीं है। इसके अलावा, मुझे नहीं लगता कि आखिरी बार क्या है। – itsadok

2

sre_parse के अंदर से कुछ मदद कर सकता है।

पहली नज़र, हो सकता है की तर्ज पर कुछ में:

>>> import sre_parse 
>>> sre_parse.parse('(\d)\d(\d)') 
[('subpattern', (1, [('in', [('category', 'category_digit')])])), 
('in', [('category', 'category_digit')]), 
('subpattern', (2, [('in', [('category', 'category_digit')])]))] 

अर्थात प्रकार 'subpattern' के आइटम गिनती:,

import sre_parse 

def count_patterns(regex): 
    """ 
    >>> count_patterns('foo: \d') 
    0 
    >>> count_patterns('foo: (\d)') 
    1 
    >>> count_patterns('foo: (\d(\s))') 
    1 
    """ 
    parsed = sre_parse.parse(regex) 
    return len([token for token in parsed if token[0] == 'subpattern']) 

ध्यान दें कि हम केवल यहाँ रूट स्तर पैटर्न गिनती कर रहे हैं तो पिछले उदाहरण केवल 1. रिटर्न इसे बदलने के लिए, टोकन रिकर्सिवली की खोज की आवश्यकता होगी।

0

गलत हो सकता है, लेकिन मुझे नहीं लगता कि समूह की संख्या को खोजने का कोई तरीका है जो रेगेक्स से मेल खाता था। एकमात्र तरीका यह है कि मैं इस काम को जिस तरह से करना चाहता हूं, वह है कि आप अपने विशेष रेगेक्स को तर्क के रूप में अपेक्षाओं की संख्या को पारित करना चाहते हैं।

हालांकि स्पष्टीकरण के लिए: जब खोज सफल होता है, तो आप केवल पहले मैच को वापस लौटना चाहते हैं, लेकिन जब यह विफल हो जाता है तो आप रिक्त तारों की एक सूची चाहते हैं? क्योंकि टिप्पणी एक सूची के रूप में वापस आने वाले सभी मैचों को दिखाने के लिए प्रतीत होती है।

0

एक आधार के रूप में अपने कोड का उपयोग करना:

def groups(regexp, s): 
    """ Returns the first result of re.findall, or an empty default 

    >>> groups(r'(\d)(\d)(\d)', '123') 
    ('1', '2', '3') 
    >>> groups(r'(\d)(\d)(\d)', 'abc') 
    ('', '', '') 
    """ 
    import re 
    m = re.search(regexp, s) 
    if m: 
     return m.groups() 
    return ('',) * len(m.groups()) 
+0

यह कोई अपवाद फेंक देगा जब कोई मिलान नहीं मिलेगा – itsadok

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