代码之家  ›  专栏  ›  技术社区  ›  Curd

匹配python中的组

  •  40
  • Curd  · 技术社区  · 14 年前

    在python中,有没有一种方法可以访问匹配组而不显式地创建匹配对象(或者另一种方法来美化下面的示例)?

    下面是一个例子来阐明我提出这个问题的动机:

    遵循Perl代码

    if    ($statement =~ /I love (\w+)/) {
      print "He loves $1\n";
    }
    elsif ($statement =~ /Ich liebe (\w+)/) {
      print "Er liebt $1\n";
    }
    elsif ($statement =~ /Je t\'aime (\w+)/) {
      print "Il aime $1\n";
    }
    

    翻译成python

    m = re.search("I love (\w+)", statement)
    if m:
      print "He loves",m.group(1)
    else:
      m = re.search("Ich liebe (\w+)", statement)
      if m:
        print "Er liebt",m.group(1)
      else:
        m = re.search("Je t'aime (\w+)", statement)
        if m:
          print "Il aime",m.group(1)
    

    看起来很尴尬(如果是层叠,匹配对象创建)。

    4 回复  |  直到 14 年前
        1
  •  34
  •   PaulMcG    14 年前

    您可以创建一个返回调用match的布尔结果的小类, 保留匹配的组以供后续检索:

    import re
    
    class REMatcher(object):
        def __init__(self, matchstring):
            self.matchstring = matchstring
    
        def match(self,regexp):
            self.rematch = re.match(regexp, self.matchstring)
            return bool(self.rematch)
    
        def group(self,i):
            return self.rematch.group(i)
    
    
    for statement in ("I love Mary", 
                      "Ich liebe Margot", 
                      "Je t'aime Marie", 
                      "Te amo Maria"):
    
        m = REMatcher(statement)
    
        if m.match(r"I love (\w+)"): 
            print "He loves",m.group(1) 
    
        elif m.match(r"Ich liebe (\w+)"):
            print "Er liebt",m.group(1) 
    
        elif m.match(r"Je t'aime (\w+)"):
            print "Il aime",m.group(1) 
    
        else: 
            print "???"
    
        2
  •  18
  •   S.Lott    14 年前

    效率低,但外观简单:

    m0 = re.match("I love (\w+)", statement)
    m1 = re.match("Ich liebe (\w+)", statement)
    m2 = re.match("Je t'aime (\w+)", statement)
    if m0:
      print "He loves",m0.group(1)
    elif m1:
      print "Er liebt",m1.group(1)
    elif m2:
      print "Il aime",m2.group(1)
    

    Perl的问题在于隐式更新了一些隐藏变量。这在Python中很难实现,因为您需要有一个赋值语句来实际更新任何变量。

    重复次数少(效率高)的版本如下:

    pats = [
        ("I love (\w+)", "He Loves {0}" ),
        ("Ich liebe (\w+)", "Er Liebe {0}" ),
        ("Je t'aime (\w+)", "Il aime {0}")
     ]
    for p1, p3 in pats:
        m= re.match( p1, statement )
        if m:
            print p3.format( m.group(1) )
            break
    

    一些Perl人喜欢的一个小变化:

    pats = {
        "I love (\w+)" : "He Loves {0}",
        "Ich liebe (\w+)" : "Er Liebe {0}",
        "Je t'aime (\w+)" : "Il aime {0}",
    }
    for p1 in pats:
        m= re.match( p1, statement )
        if m:
            print pats[p1].format( m.group(1) )
            break
    

    这几乎不值得一提,除非它有时来自Perl程序员。

        3
  •  4
  •   ghostdog74    14 年前

    这不是regex解决方案。

    alist={"I love ":""He loves"","Je t'aime ":"Il aime","Ich liebe ":"Er liebt"}
    for k in alist.keys():
        if k in statement:
           print alist[k],statement.split(k)[1:]
    
        4
  •  1
  •   Adam Rosenfield    14 年前

    您可以创建一个助手函数:

    def re_match_group(pattern, str, out_groups):
        del out_groups[:]
        result = re.match(pattern, str)
        if result:
            out_groups[:len(result.groups())] = result.groups()
        return result
    

    然后像这样使用:

    groups = []
    if re_match_group("I love (\w+)", statement, groups):
        print "He loves", groups[0]
    elif re_match_group("Ich liebe (\w+)", statement, groups):
        print "Er liebt", groups[0]
    elif re_match_group("Je t'aime (\w+)", statement, groups):
        print "Il aime", groups[0]
    

    它有点笨重,但能完成任务。