1
>>> re.findall(r"(?:do|re|mi)+", "mimi")
['mimi']
>>> re.findall(r"(do|re|mi)+", "mimi")
['mi']

根据我对定义的理解,它应该产生相同的答案。(...)和应该之间的唯一区别(?:...)是我们以后是否可以使用反向引用。我错过了什么吗?

(...)

匹配括号内的任何正则表达式,并指示组的开始和结束;组的内容可以在执行匹配后检索,并且可以稍后在字符串中使用 \number 特殊序列进行匹配,如下所述。要匹配文字 '(' 或 ')',请使用 ( 或 ),或将它们包含在字符类中:[(] [)]。

(?:...)

常规括号的非捕获版本。匹配括号内的任何正则表达式,但组匹配的子字符串在执行匹配后无法检索或稍后在模式中引用。

4

3 回答 3

4

(?:...)没有分组。所以,在

re.findall(r"(?:do|re|mi)+", "mimi")

它为整个正则表达式的每个匹配返回一个值,在这种情况下是mi字符串的两倍,因此是一个包含一个元素的列表,mimi.

dos(...)分组并将findall()为每个匹配的带括号的字符串返回一个值。在

re.findall(r"(do|re|mi)+", "mimi")

匹配mi并将其保存为组 1,然后继续并再次匹配mi,但在同一个带括号的字符串内,因此覆盖组 1,最后它返回组 1 中的值,它只是第二个mi

于 2013-10-20T21:58:00.970 回答
1

虽然匹配相同,但非分组版本(?...)

  • 效率稍高一些,因为避免了存储对捕获组的引用的工作
  • 可能允许更多捕获的组。大多数正则表达式风格限制为 9 个单独的组,这些组可以被反向引用。因为只使用一个数字来命名它们(第 0 组是整个匹配项,因此 9 而不是 10)
于 2013-10-20T21:51:22.797 回答
1

不,你没有错过任何东西。的用途(?:...)是能够在不将不需要的项目放在反向引用/匹配的子字符串中的情况下对事物进行分组。

于 2013-10-20T21:44:08.017 回答