代码之家  ›  专栏  ›  技术社区  ›  Sundar R

如何在python中搜索regex匹配项?

  •  5
  • Sundar R  · 技术社区  · 15 年前

    我需要对多个(排它的意思是匹配其中一个的字符串不能匹配任何其他的)regex尝试一个字符串,并根据匹配的代码执行不同的代码段。我现在拥有的是:

    m = firstre.match(str)
    if m:
        # Do something
    
    m = secondre.match(str)
    if m:
        # Do something else
    
    m = thirdre.match(str)
    if m:
        # Do something different from both
    

    除了丑陋之外,这段代码与所有的regex都匹配,即使在匹配了其中一个regex之后(比如firstre),这也是低效的。我尝试使用:

    elif m = secondre.match(str)
    

    但了解到,在if语句中不允许赋值。

    有没有一种优雅的方式来实现我想要的?

    7 回复  |  直到 15 年前
        1
  •  4
  •   Philippe F    15 年前
    def doit( s ):
    
        # with some side-effect on a
        a = [] 
    
        def f1( s, m ):
            a.append( 1 )
            print 'f1', a, s, m
    
        def f2( s, m ):
            a.append( 2 )
            print 'f2', a, s, m
    
        def f3( s, m ):
            a.append( 3 )
            print 'f3', a, s, m
    
        re1 = re.compile( 'one' )
        re2 = re.compile( 'two' )
        re3 = re.compile( 'three' )
    
    
        func_re_list = (
            ( f1, re1 ), 
            ( f2, re2 ), 
            ( f3, re3 ),
        )
        for myfunc, myre in func_re_list:
            m = myre.match( s )
            if m:
                myfunc( s, m )
                break
    
    
    doit( 'one' ) 
    doit( 'two' ) 
    doit( 'three' ) 
    
        2
  •  3
  •   Ants Aasma    15 年前

    这可能有点过于工程化了解决方案,但您可以将它们作为一个单独的regexp与命名组组合,并查看哪个组匹配。这可以封装为一个助手类:

    import re
    class MultiRe(object):
        def __init__(self, **regexps):
            self.keys = regexps.keys()
            self.union_re = re.compile("|".join("(?P<%s>%s)" % kv for kv in regexps.items()))
    
        def match(self, string, *args):
            result = self.union_re.match(string, *args)
            if result:
                for key in self.keys:
                    if result.group(key) is not None:
                        return key
    

    查找方式如下:

    multi_re = MultiRe(foo='fo+', bar='ba+r', baz='ba+z')
    match = multi_re.match('baaz')
    if match == 'foo':
         # one thing
    elif match == 'bar':
         # some other thing
    elif match == 'baz':
         # or this
    else:
         # no match
    
        3
  •  3
  •   Robert Rossney    15 年前

    这是一个很好的无证件申请,但很有用 re.Scanner 班级。

        4
  •  1
  •   Edan Maor    15 年前

    一些想法,它们都不一定是好的,但它可能很适合您的代码:

    把代码放在一个单独的函数中,即 MatchRegex() ,返回它匹配的regex。这样,在函数内部,您可以在匹配第一个(或第二个)regex之后使用返回,这意味着您将失去效率。

    当然,你可以一直使用嵌套 if 声明:

    m = firstre.match(str)
    if m:
       # Do something
    else:
        m = secondre.match(str)
        ...
    

    我真的没有任何理由不去嵌套 如果 它们很容易理解,而且效率和你想要的一样高。为了他们的简单,我会选择他们。

        5
  •  1
  •   Greg Bacon    15 年前

    你可以使用

    def do_first(str, res, actions):
      for re,action in zip(res, actions):
        m = re.match(str)
        if m:
          action(str)
          return
    

    例如,假设你已经定义了

    def do_something_1(str):
      print "#1: %s" % str
    
    def do_something_2(str):
      print "#2: %s" % str
    
    def do_something_3(str):
      print "#3: %s" % str
    
    firstre  = re.compile("foo")
    secondre = re.compile("bar")
    thirdre  = re.compile("baz")
    

    那就叫它

    do_first("baz",
             [firstre,        secondre,       thirdre],
             [do_something_1, do_something_2, do_something_3])
    
        6
  •  0
  •   Jason Orendorff Oliver    15 年前

    可能是提前归还?

    def doit(s):
        m = re1.match(s)
        if m:
            # Do something
            return
    
        m = re2.match(s)
        if m:
            # Do something else
            return
    
        ...
    

    蚂蚁的回答也很好。如果你更喜欢较少的脚手架,你可以用 verbose regex syntax .

    re = re.compile(r'''(?x)    # set the verbose flag
        (?P<foo> fo+ )
      | (?P<bar> ba+r )
      | #...other alternatives...
    ''')
    
    def doit(s):
        m = re.match(s)
        if m.group('foo'):
            # Do something
        elif m.group('bar'):
            # Do something else
        ...
    

    我做了很多。它很快,而且能与 re.finditer .

        7
  •  0
  •   kibitzer    15 年前

    用一个elif来做,以防你只需要一个正确/错误的正则表达式匹配:

    if regex1.match(str):
        # do stuff
    elif regex2.match(str):
        # and so on