Python正则表达式:重复限定符{n}和等效元组之间的区别不明确

时间:2018-04-17 21:23:08

标签: python regex

为什么 xx 会产生与 x {2} 不同的内容? 请看下面的例子:

import re

lines = re.findall(r'".*?"".*?"', '"x""y"')
print(lines) # yields: ['"x""y"']

lines = re.findall(r'(".*?"){2}', '"x""y"')
print(lines) # yields: ['"y"']

4 个答案:

答案 0 :(得分:0)

第一个表达式是“X然后是Y,其中Y意外地匹配与X”相同的东西。

第二个表达式是“(X){重复两次}”。第1组不能包含XX,因为第1组与XX不匹配。它匹配X.

换句话说:组内容不会因为组外的量词而改变。

补救第二个表达式的一种方法是创建一个外部组(并使内部组不捕获)

lines = re.findall(r'((?:".*?"){2})', '"x""y"')

答案 1 :(得分:0)

根据documentation of findall,如果正则表达式中有一个组,它将返回这些组的列表,可以是2个组的元组,也可以是1个组的字符串。在您的情况下,您的两个正则表达式不仅仅是xxx{2},而是第二个正则表达式(x){2},当第一个正则表达式没有组时,它有一个组。

因此,"x"第一次匹配该组,然后"y"第二次匹配该组。这可以满足您的整体正则表达式,但"y"会覆盖"x"以获取组1的值。

在您的示例中解决此问题的最简单方法是将您的群组转换为不匹配的群组:(?:".*?"){2}。如果您需要两个组,一个用于"x",另一个用于"y",则需要重复两次组:(".*?")(".*?")。您可以使用命名组来简化此重复。

答案 2 :(得分:0)

关于您的第二种模式(".*?"){2}

来自rules of matching

的引用
  

如果一个组包含在多次匹配的模式的一部分中,则返回最后一个匹配。

findall执行以下操作:

  

如果模式中存在一个或多个组,则返回组列表;

您的模式(".*?"){2}表示(".*?")应该连续两次匹配,并且根据第一条规则,仅捕获最后一个匹配的内容。

对于您的数据findall只查找序列(".*?"){2}一次,因此它会返回一个列表,其中包含单个匹配项的最后一个捕获组:['"y"']

这个例子会更明显:

import re
print (re.findall(r'(\d){2}', 'a12b34c56'))
# ['2', '4', '6']

您可以看到findall找到序列(\d){2}三次,并且每次都会返回组(\d)的最后捕获内容。

现在谈谈你的第一个模式:".*?"".*?" 这个不包含子组,并且,再次根据findall,在这种情况下它返回:

  

字符串中模式的所有非重叠匹配,作为字符串列表。

因此,对于您的数据,它是['"x""y"']

答案 3 :(得分:0)

AFAIK,findall()capture group first,如果应用的正则表达式中有任何捕获组,则findall()仅返回捕获组值。

仅当应用的正则表达式中没有捕获组时,findall()才会返回fullmatch values

因此,如果您希望findall()返回fullmatch value,那么您不能像这样在正则表达式中使用捕获组

(?:".*?"){2}

其中(?: ... )表示non-capture group

因此,在python中

print(re.findall(r'(?:".*?"){2}', '"x""y"'))