正则表达式如何{m,n}?在Python工作?

时间:2015-04-24 15:51:03

标签: python regex

来自re模块的Python文档:

  

{M,N}?

     

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

我对这是如何工作感到困惑。这与{m}有什么不同?我不知道模式是否可能匹配超过m次重复的情况。如果连续重复m+1,则还有m。我错过了什么?

4 个答案:

答案 0 :(得分:7)

然而,单独包含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正则表达式的好资源。

答案 1 :(得分:4)

我认为通过以下示例来看待两者之间差异的方法是:

>>> 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']

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

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

这就是为什么你看到'b {3,5}?c'和'bbbbbc'可能出人意料的结果。虽然正则表达式是贪婪的,但是在模式匹配失败之前它仍然不会推进它的第一个迭代器,这就是为什么具有5'b'字符的子字符串与非贪婪的正则表达式匹配,即使它不是最短的模式匹配

答案 2 :(得分:-1)

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

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

但是

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

答案 3 :(得分:-2)

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

现在我们有模式= a {3,5} 它匹配的字符串是:{aaa,aaaa,aaaaa} 但在这里我们有#34; aaaaa"因为我们只有一个选择。

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

因此,尽可能采用最少的项目,非贪婪。

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

这将是很好的帮助,我们会立即检查它匹配的内容以及它不匹配的内容