【问题标题】:python - regex search and findallpython - 正则表达式搜索和 findall
【发布时间】:2011-12-27 22:41:49
【问题描述】:

我需要在字符串中为给定的正则表达式找到所有匹配项。我一直在使用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']

在这种情况下,search() 返回我需要的内容(最长匹配),但 findall() 的行为不同,尽管文档暗示它应该是相同的:

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

  • 为什么行为不同?

  • 如何使用findall()(或其他)实现search() 的结果?

【问题讨论】:

    标签: python regex search string-matching findall


    【解决方案1】:

    好的,我知道发生了什么……来自文档:

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

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

    一种解决方案是用一个组包围整个正则表达式,像这样

    regex = re.compile('((\d+,?)+)')
    

    然后,它将返回 [('9,000,000', '000')],这是一个包含两个匹配组的元组。当然,你只关心第一个。

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

    regex = re.compile('((\d+,)*\d+)')
    

    为了避免匹配诸如“这是一个错误的数字 9,123”之类的内容,

    编辑。

    这是一种避免用括号括住表达式或处理元组的方法

    s = "..."
    regex = re.compile('(\d+,?)+')
    it = re.finditer(regex, s)
    
    for match in it:
      print match.group(0)
    

    finditer 返回一个迭代器,您可以使用它来访问找到的所有匹配项。这些匹配对象与 re.search 返回的相同,因此 group(0) 返回您期望的结果。

    【讨论】:

    • 感谢您的解释。事实证明finditer 实际上更适合我按照您的建议所做的事情。正则表达式来自用户输入,因此我无法控制它。
    【解决方案2】:

    @aleph_null 的answer 正确解释了导致您的问题的原因,但我认为我有更好的解决方案。使用这个正则表达式:

    regex = re.compile(r'\d+(?:,\d+)*')
    

    它更好的一些原因:

    1. (?:...) 是一个非捕获组,因此每场比赛您只能得到一个结果。

    2. \d+(?:,\d+)* 是一种更好的正则表达式,效率更高且返回误报的可能性更低。

    3. 如果可能,您应该始终将 Python 的原始字符串用于正则表达式;您不太可能对正则表达式转义序列(如 word 边界\b)被解释为字符串文字转义序列(如 退格\b )。

    【讨论】:

    • 谢谢艾伦!我之前应该提到过,但我无法控制正则表达式,因为它是用户输入..
    • 没问题!但是,为了记录,让用户输入要由您的应用程序执行的正则表达式是一个坏主意。当他们写得不好(或只是匆忙输入)的正则表达式无法匹配或导致系统崩溃时,他们会为此责备。 ;)
    猜你喜欢
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 2015-08-13
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    相关资源
    最近更新 更多