【问题标题】:How does regex {m,n}? work in Python?正则表达式{m,n}如何?在 Python 中工作?
【发布时间】:2015-04-24 15:51:02
【问题描述】:

来自re 模块的 Python 文档:

{m,n}?

使生成的 RE 匹配前一个 RE 的 m 到 n 个重复,尝试匹配尽可能少的重复。这是先前限定符的非贪婪版本。例如,在 6 个字符的字符串 'aaaaaa' 上,a{3,5} 将匹配 5 个 'a' 字符,而 a{3,5}?只会匹配 3 个字符。

我对它的工作原理感到困惑。这与{m} 有何不同?我看不出模式匹配的次数超过m 重复次数的情况。如果连续有m+1重复,那么也有m。我错过了什么?

【问题讨论】:

  • 您是否考虑过设置一些测试用例并进行试验?您应该先这样做,然后如果您对结果感到困惑,请将其发布在您的问题中,并附上您的期望
  • 这只是您想要匹配的重复次数的范围,而不是确切的数字。
  • 请注意{m,n}{m,n}?(注意?)略有不同。获取“正则表达式非贪婪”以获取更多信息。
  • @ColonelThirtyTwo 是的,我了解{m,n}{m,n}? 之间的区别我无法理解{m}{m,n}? 之间的区别
  • 我很困惑为什么有 6 个投票的答案没有回答问题

标签: python regex


【解决方案1】:

然而,一个只包含a{3,5}? 和一个模式:a{3} 的正则表达式确实会匹配相同的东西(即re.match(r'a{3,5}?', 'aaaaa').group(0)re.match(r'a{3}', 'aaaaa').group(0) 都将返回'aaa'),当您查看包含这两个元素的模式时,模式之间的差异就会变得清晰。假设您的模式是a{3,5}?b,那么aaabaaaabaaaaab 将被匹配。如果您只使用了a{3}b,那么只有aaab 会得到匹配。 aaaabaaaaab 不会。

查看 Shashank 的回答,了解更多可以消除这种差异的示例,或者自己测试一下。我发现这个site 是一个很好的资源,可以用来测试python 正则表达式。

【讨论】:

    【解决方案2】:

    我认为看两者区别的方法是通过以下例子:

    >>> re.findall(r'ab{3,5}?', 'abbbbb')
    ['abbb']
    >>> re.findall(r'ab{3}', 'abbbbb')
    ['abbb']
    

    这两次运行的结果与预期相同,但让我们看看一些差异。

    区别 1:子模式上的范围量词可以让您匹配包含该子模式的大量模式。如果您使用精确的量词,这可以让您找到通常不会有的匹配项:

    >>> re.findall(r'ab{3,5}?c', 'abbbbbc')
    ['abbbbbc']
    >>> re.findall(r'ab{3}c', 'abbbbbc')
    []
    

    区别 2:贪婪并不一定意味着“匹配可能的最短子模式”。它实际上有点像“从可能开始匹配的最左边的不匹配索引开始匹配可能的最短子模式”:

    >>> re.findall(r'b{3,5}?c', 'bbbbbc')
    ['bbbbbc']
    >>> re.findall(r'b{3}c', 'bbbbbc')
    ['bbbc']
    

    我认为正则表达式是一种结构,它使用两个指向字符串中索引的迭代器从左到右扫描字符串。第一个迭代器标志着下一个可能模式的开始。第二个迭代器从第一个迭代器开始遍历子字符串的后缀,并尝试完成模式。 第一个迭代器仅在构造确定正则表达式模式不可能匹配从该索引开始的字符串时才前进。因此,为量词定义一个范围将使第一个迭代器继续匹配 sub - 超出指定最小值的模式即使量词是非贪婪的

    一个非贪婪的正则表达式将停止它的第二个迭代器 soon 因为模式可以停止,但一个贪婪的正则表达式将“保存”匹配模式的位置并继续搜索更长的模式。如果找到较长的模式,则使用该模式,如果未找到,则使用之前保存在内存中的较短模式。

    这就是为什么您看到 'b{3,5}?c' 和 'bbbbbc' 的结果可能令人惊讶。尽管正则表达式是贪婪的,但它仍然永远不会推进其第一个迭代器,直到模式匹配失败,这就是为什么非贪婪正则表达式匹配具有 5 个 'b' 字符的子字符串 即使它不是可匹配的最短模式

    【讨论】:

      【解决方案3】:

      SwankSwashbucklers 的回答描述了贪婪的版本。 ? 使其不贪婪,这意味着它将尝试匹配尽可能少的项目,这意味着

      `re.match('a{3,5}?b', 'aaaab').group(0)` # returns `'aaaab'` 
      

      但是

      `re.match('a{3,5}?', 'aaaa').group(0)` # returns `'aaa'`
      

      【讨论】:

      • re.match 将匹配两个字符串,无论它是否贪婪。这个答案具有误导性,并且会混淆 IMO。一个更好的主意是指出 a{3,5}?a{3,5} 模式与字符串 'aaaaaa' 之间的区别。
      • 谢谢。现在更正了,还有第二个错误也更正了
      • 它仍然没有真正显示出非贪婪和贪婪之间的区别。我建议显示re.findall(r'a{3,5}?', 'a'*6)re.findall(r'a{3,5}', 'a'*6) 第一个会找到两个匹配项,第二个只会找到一个。
      • 是的。第一种情况匹配 4 个 a,第二个匹配 3 个。两个字符串都有 4 个 a
      • OP 询问{m}{m,n}? 之间的区别
      【解决方案4】:

      假设我们有一个要搜索的字符串是: str =“aaaaa”

      现在我们有模式 = a{3,5} 它匹配的字符串是:{aaa,aaaa,aaaaa} 但是这里我们将字符串设为“aaaaa”,因为我们只有一个选项。

      现在假设我们有模式 = a{3,5}? 在这种情况下,它只匹配“aaa”而不是“aaaaa”。

      因此它尽可能少的项目,不贪心。

      请尝试使用在线正则表达式:https://pythex.org/

      这将是很大的帮助,我们会立即检查匹配的内容和不匹配的内容

      【讨论】:

        猜你喜欢
        • 2012-12-02
        • 1970-01-01
        • 2021-03-31
        • 1970-01-01
        • 2015-06-19
        • 2010-09-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多