【问题标题】:Regular expression for repeating sequence重复序列的正则表达式
【发布时间】:2012-01-20 22:39:55
【问题描述】:

我想匹配由逗号分隔的三个字符的字母序列(只允许使用字母 'a'、'b'、'c')(最后一组不以逗号结尾)。

例子:

abc,bca,cbb
ccc,abc,aab,baa
bcb

我写了以下正则表达式:

re.match('([abc][abc][abc],)+', "abc,defx,df")

但是它不能正常工作,因为对于上面的例子:

>>> print bool(re.match('([abc][abc][abc],)+', "abc,defx,df")) # defx in second group
True
>>> print bool(re.match('([abc][abc][abc],)+', "axc,defx,df")) # 'x' in first group
False

它似乎只检查第一组三个字母,但它忽略了其余的。如何正确编写这个正则表达式?

【问题讨论】:

    标签: python regex


    【解决方案1】:

    强制性的“你不需要正则表达式”解决方案:

    all(letter in 'abc,' for letter in data) and all(len(item) == 3 for item in data.split(','))
    

    【讨论】:

      【解决方案2】:

      你要求它用你的正则表达式找到的是“至少三个字母 a、b、c”——这就是“+”给你的。之后发生的任何事情对正则表达式都无关紧要。您可能想要包含“$”,意思是“行尾”,以确保该行必须全部由允许的三元组组成。但是,在当前形式中,您的正则表达式还要求最后一个三元组以逗号结尾,因此您应该明确编码并非如此。 试试这个:

      re.match('([abc][abc][abc],)*([abc][abc][abc])$'
      

      这会找到任意数量的允许三元组,后跟逗号(可能为零),然后是不带逗号的三元组,然后是行尾。

      编辑:不需要包含“^”(字符串开头)符号,因为match 方法已经仅在字符串开头检查匹配项。

      【讨论】:

      • 您很好地解释了正则表达式在开头和结尾都需要锚点,但您的解决方案中没有包含^
      • 模式的开头不需要^,因为使用的是方法match()。我纠正了,我赞成。欢迎来到 SO ,索尼娅
      • @eyquem,谢谢!写第一个答案非常可怕:)
      • @Sonya 实际上,您应该更正这句话:“您可能希望包含“^”,表示“行首”和“$”,表示“ end of the line"," 我不想在别人的帖子中做更多的小修正。
      【解决方案3】:

      如果您的目标是验证字符串是否由字母 a、b 和 c 的三元组组成:

      for ss in ("abc,bbc,abb,baa,bbb",
                 "acc",
                 "abc,bbc,abb,bXa,bbb",
                 "abc,bbc,ab,baa,bbb"):
          print ss,'   ',bool(re.match('([abc]{3},?)+\Z',ss))
      

      结果

      abc,bbc,abb,baa,bbb     True
      acc     True
      abc,bbc,abb,bXa,bbb     False
      abc,bbc,ab,baa,bbb     False
      

      \Z 表示:字符串的结尾。它的存在迫使匹配一直到字符串的最后

      顺便说一句,我也喜欢索尼娅的形式,在某种程度上它更清晰:

      bool(re.match('([abc]{3},)*[abc]{3}\Z',ss))
      

      【讨论】:

        【解决方案4】:

        不使用正则表达式的替代方法(尽管是蛮力方式):

        >>> def matcher(x):
                total = ["".join(p) for p in itertools.product(('a','b','c'),repeat=3)]
                    for i in x.split(','):
                        if i not in total:
                            return False
                 return True
        
        >>> matcher("abc,bca,aaa")
            True
        >>> matcher("abc,bca,xyz")
            False
        >>> matcher("abc,aaa,bb")
            False
        

        【讨论】:

          【解决方案5】:

          尝试以下正则表达式:

          ^[abc]{3}(,[abc]{3})*$
          

          ^...$从字符串的开头到结尾
          [...]给定字符之一
          ...{3}之前短语的三次
          (...)*0到n次括号内的字符

          【讨论】:

            【解决方案6】:

            您需要遍历找到的值序列。

            data_string = "abc,bca,df"
            
            imatch = re.finditer(r'(?P<value>[abc]{3})(,|$)', data_string)
            
            for match in imatch:
                print match.group('value')
            

            所以检查字符串是否匹配模式的正则表达式将是

            data_string = "abc,bca,df"
            
            match = re.match(r'^([abc]{3}(,|$))+', data_string)
            
            if match:
                print "data string is correct"
            

            【讨论】:

              【解决方案7】:

              你的结果并不奇怪,因为正则表达式

              ([abc][abc][abc],)+
              

              尝试匹配一个字符串,该字符串包含三个字符[abc],后跟一个或多个逗号anywhere。所以最重要的部分是确保字符串中没有更多内容 - 正如 scessor 建议的那样,将^(字符串开头)和$(字符串结尾)添加到正则表达式中。

              【讨论】:

                猜你喜欢
                • 2013-12-30
                • 1970-01-01
                • 2021-07-26
                • 1970-01-01
                • 2012-02-28
                • 1970-01-01
                相关资源
                最近更新 更多