2009-02-28 8 views
11

Mój dylemat: Przekazuję mojej funkcji ciąg znaków, który muszę następnie wykonać wiele manipulacji regex na. Logika polega na tym, że jeśli w pierwszym wyrażeniu występuje dopasowanie, zrób jedno. Jeśli nie pasuje, sprawdź mecz z drugim i zrób coś innego, jeśli nie, sprawdź trzeci, i tak dalej. mógłby zrobić coś takiego:Jak zwięźle kaskadowo za pośrednictwem wielu wyrażeń regularnych w Pythonie

if re.match('regex1', string): 
    match = re.match('regex1', string) 
    # Manipulate match.group(n) and return 
elif re.match('regex2', string): 
    match = re.match('regex2', string) 
    # Do second manipulation 
[etc.] 

to jednak czuje się niepotrzebnie gadatliwy, i zwykle kiedy to przypadek to oznacza, że ​​istnieje lepszy sposób, że jestem albo widokiem lub jeszcze nie wiedzą.

Czy ktoś ma sugestię, jak to zrobić lepiej (lepiej z punktu widzenia wyglądu kodu, punktu użycia pamięci lub obu)?

+0

dupicate: http://stackoverflow.com/questions/122277/how-do-you-translate-thisregular-expression-idiom-from-perl-into-python –

Odpowiedz

10

Podobne pytanie z powrotem w Wrzesień: How do you translate this regular-expression idiom from Perl into Python?

Używanie zmiennych globalnych w module może nie jest najlepszym sposobem, aby to zrobić, ale przekształcenie go w klasie:

import re 

class Re(object): 
    def __init__(self): 
    self.last_match = None 
    def match(self,pattern,text): 
    self.last_match = re.match(pattern,text) 
    return self.last_match 
    def search(self,pattern,text): 
    self.last_match = re.search(pattern,text) 
    return self.last_match 

gre = Re() 
if gre.match(r'foo',text): 
    # do something with gre.last_match 
elif gre.match(r'bar',text): 
    # do something with gre.last_match 
else: 
    # do something else 
+0

Dzięki za link! Nie znalazłem tego tematu w moich poszukiwaniach, ale jest na miejscu, co chcę zrobić. Podoba mi się pomysł wykorzystania klasy, a nie modułu. –

1

Hmm ... można użyć coś z with konstruktem ... um

class rewrapper() 
    def __init__(self, pattern, target): 
     something 

    def __enter__(self): 
     something 

    def __exit__(self): 
     something 


with rewrapper("regex1", string) as match: 
    etc 

with rewrapper("regex2", string) as match: 
    and so forth 
0

Czy manipulacje dla każdej regex podobne? Jeśli tak, to spróbuj tego:

for regex in ('regex1', 'regex2', 'regex3', 'regex4'): 
    match = re.match(regex, string) 
    if match: 
     # Manipulate match.group(n) 
     return result 
+0

Niestety manipulacje różnią się dla różnych wyrażeń regularnych; z perspektywy czasu powinienem to określić w pytaniu. –

0

tutaj swoje regexs i mecze nie są powtarzane dwukrotnie:

match = re.match('regex1', string) 
if match: 
    # do stuff 
    return 

match = re.match('regex2', string) 
if match: 
    # do stuff 
    return 
24

Generalnie w tego rodzaju sytuacjach, chcesz, aby kod „dane napędzane”. Oznacza to, że umieść ważne informacje w pojemniku i przeprowadź przez nie pętlę.

W twoim przypadku ważną informacją są pary (łańcuchowe, funkcyjne).

import re 

def fun1(): 
    print('fun1') 

def fun2(): 
    print('fun2') 

def fun3(): 
    print('fun3') 

regex_handlers = [ 
    (r'regex1', fun1), 
    (r'regex2', fun2), 
    (r'regex3', fun3) 
    ] 

def example(string): 
    for regex, fun in regex_handlers: 
     if re.match(regex, string): 
      fun() # call the function 
      break 

example('regex2') 
+0

Dzięki za tę sugestię! To właśnie miałem zamiar skończyć, ale zastąpiona wersja modułu re jest nieco lepiej dopasowana do tego projektu. –

2

miałem ten sam problem, co twój. Here's moje rozwiązanie:

import re 

regexp = { 
    'key1': re.compile(r'regexp1'), 
    'key2': re.compile(r'regexp2'), 
    'key3': re.compile(r'regexp3'), 
    # ... 
} 

def test_all_regexp(string): 
    for key, pattern in regexp.items(): 
     m = pattern.match(string) 
     if m: 
      # do what you want 
      break 

It'sa nieznacznie zmodyfikowane rozwiązanie z odpowiedzią Extracting info from large structured text files

+0

Słowniki nie gwarantują zamówienia. Prawdopodobnie powinieneś użyć sekwencji zamiast dyktatu, aby uzyskać przewidywalne zachowanie. –

0
class RegexStore(object): 
    _searches = None 

    def __init__(self, pat_list): 
     # build RegEx searches 
     self._searches = [(name,re.compile(pat, re.VERBOSE)) for 
         name,pat in pat_list] 

    def match(self, text): 
     match_all = ((x,y.match(text)) for x,y in self._searches) 
     try: 
     return ifilter(op.itemgetter(1), match_all).next() 
     except StopIteration, e: 
     # instead of 'name', in first arg, return bad 'text' line 
     return (text,None) 

Można użyć tej klasy tak:

rs = RegexStore((('pat1', r'.*STRING1.*'), 
        ('pat2', r'.*STRING2.*'))) 
name,match = rs.match("MY SAMPLE STRING1") 

if name == 'pat1': 
    print 'found pat1' 
elif name == 'pat2': 
    print 'found pat2' 
Powiązane problemy