python-regex搜索和findall

python-regex搜索和findall,python,regex,search,string-matching,findall,Python,Regex,Search,String Matching,Findall,我需要找到给定正则表达式字符串中的所有匹配项。我一直在使用findall()来实现这一点,直到我遇到一个案例,它没有达到我的预期。例如: regex = re.compile('(\d+,?)+') s = 'There are 9,000,000 bicycles in Beijing.' print re.search(regex, s).group(0) > 9,000,000 print re.findall(regex, s) > ['000'] 在这种情况下,返回我

我需要找到给定正则表达式字符串中的所有匹配项。我一直在使用
findall()
来实现这一点,直到我遇到一个案例,它没有达到我的预期。例如:

regex = re.compile('(\d+,?)+')
s = 'There are 9,000,000 bicycles in Beijing.'

print re.search(regex, s).group(0)
> 9,000,000

print re.findall(regex, s)
> ['000']
在这种情况下,返回我需要的内容(最长匹配),但行为不同,尽管文档暗示它应该是相同的:

findall()
匹配模式的所有匹配项,而不仅仅是第一个匹配项 正如
search()
所做的那样

  • 为什么行为不同

  • 如何使用
    findall()
    (或其他东西)获得
    search()
    的结果


    • 好的,我知道发生了什么。。。从文档中:

      如果模式中存在一个或多个组,则返回组列表; 如果模式有多个组,这将是一个元组列表

      事实证明,您确实有一个组,“(\d+,?)”。。。所以,它返回的是这个组的最后一次出现,或000

      一种解决方案是由一个组包围整个正则表达式,如下所示

      regex = re.compile('((\d+,?)+)')
      
      然后,它将返回[('9000000','000')],这是一个包含两个匹配组的元组。当然,你只关心第一个

      就个人而言,我会使用以下正则表达式

      regex = re.compile('((\d+,)*\d+)')
      
      为了避免“这是一个糟糕的号码9123”之类的匹配

      编辑

      这里有一种避免表达式被括号包围或处理元组的方法

      s = "..."
      regex = re.compile('(\d+,?)+')
      it = re.finditer(regex, s)
      
      for match in it:
        print match.group(0)
      
      finditer返回一个迭代器,您可以使用该迭代器访问找到的所有匹配项。这些匹配对象与re.search返回的对象相同,因此组(0)返回您期望的结果。

      @aleph\u null's正确地解释了导致问题的原因,但我认为我有更好的解决方案。使用此正则表达式:

      regex = re.compile(r'\d+(?:,\d+)*')
      
      这更好的一些原因:

    • (?:…)
      是非捕获组,因此每次匹配只能得到一个结果

    • \d+(?:,\d+*
      是一个更好的正则表达式,效率更高,并且不太可能返回误报

    • 如果可能的话,您应该始终为正则表达式使用Python的原始字符串;对于正则表达式转义序列(如
      \b
      表示单词边界)被解释为字符串文字转义序列(如
      \b
      表示退格),您不太可能感到惊讶


    • 谢谢你的解释。事实证明,
      finditer
      实际上更适合我按照你的建议所做的事情。正则表达式来自用户输入,所以我无法控制它。谢谢艾伦!我应该在前面提到过,但是我不能控制正则表达式,因为它是用户输入..没问题!但是,作为记录,让用户输入要由你的应用程序执行的正则表达式是个坏主意。当他们写得不好(或只是匆忙键入)的正则表达式无法匹配或使系统崩溃时,他们会为此责备你。;)