Python正则表达式中的"?:"代表什么意思?

9
下面是Python正则表达式。其中?:表示什么意思?整个表达式的作用是什么?它如何匹配MAC地址,例如"00:07:32:12:ac:de:ef"?
re.compile(([\dA-Fa-f]{2}(?:[:-][\dA-Fa-f]{2}){5}), string)  
4个回答

14
"

(?:...) 表示一组非捕获分组括号。

通常,在正则表达式中写 (...) 时,它会'捕获'匹配的内容。当你使用非捕获版本时,它不会捕获。

在正则表达式与特定字符串匹配后,你可以通过 regex 中的方法来获取匹配的各个部分,这些方法在 re 包中。

"
这个正则表达式如何匹配MAC地址"00:07:32:12:ac:de:ef"?
这是一个与你最初提出的问题不同的问题。然而,正则表达式部分是:
([\dA-Fa-f]{2}(?:[:-][\dA-Fa-f]{2}){5})

最外层的括号是捕获括号;当你成功地使用正则表达式对字符串进行匹配时,它们所包围的内容将可用。 [\dA-Fa-f]{2} 部分匹配一个数字 (\d) 或十六进制数字 A-Fa-f],成对出现 {2},后面跟着一个非捕获分组,其中匹配的内容是冒号或破折号 (:-),然后再跟着另一对十六进制数字,整个过程重复5次。
p = re.compile('([\dA-Fa-f]{2}(?:[:-][\dA-Fa-f]{2}){5})')
m = p.match("00:07:32:12:ac:de:ef")
if m:
    m.group(1)

最后一行应该打印字符串"00:07:32:12:ac:de",因为这是字符串中的7对总共6对十六进制数字的第一组。实际上,外部分组括号是多余的,如果省略,m.group(0)也可以工作(即使有括号)。如果您需要匹配7对,则将5更改为6。如果您需要拒绝它们,则需要在正则表达式中添加锚点。
p = re.compile('^([\dA-Fa-f]{2}(?:[:-][\dA-Fa-f]{2}){5})$')

插入符号^匹配字符串的开头;美元符号$匹配字符串的结尾。使用数字5,它将无法匹配您的示例字符串。如果使用数字6代替5,它将能够匹配您的字符串。

谢谢,但是这个正则表达式如何匹配MAC地址“00:07:32:12:ac:de:ef”? - Hari
@rawb ... 它能正常工作,而且作为一个组,re.findall 将其打印为一个单一的组。 - Hari
看起来删除?:是可以的,那么(?:)的目的是什么呢?只是为了提高效率吗?谢谢!另外,在re.compile()中的re模式应该用单引号(')或双引号(")括起来。 - Kai
@Kai — 你可以直接删除?:,但是你需要重新编号你的捕获组 — 你多了一个捕获组。 - Jonathan Leffler
@Kai:谢谢你指出缺少引号的问题,我已经添加了它们。 - Jonathan Leffler
@JonathanLeffler 我明白了。非常感谢。 - Kai

6

在替换中使用?:,如(?:...),可以使组不捕获。在查找时没有意义。

你的正则表达式的含义是

r"""
(                   # Match the regular expression below and capture its match into backreference number 1
   [\dA-Fa-f]          # Match a single character present in the list below
                          # A single digit 0..9
                          # A character in the range between “A” and “F”
                          # A character in the range between “a” and “f”
      {2}                 # Exactly 2 times
   (?:                 # Match the regular expression below
      [:-]                # Match a single character present in the list below
                             # The character “:”
                             # The character “-”
      [\dA-Fa-f]          # Match a single character present in the list below
                             # A single digit 0..9
                             # A character in the range between “A” and “F”
                             # A character in the range between “a” and “f”
         {2}                 # Exactly 2 times
   ){5}                # Exactly 5 times
)
"""

希望这可以帮助到您。

谢谢,但是这个正则表达式如何匹配MAC地址“00:07:32:12:ac:de:ef”? - Hari
是的,它可以工作...谢谢...但我想要答案作为一个单一的组。 - Hari
尝试使用这个正则表达式:(?is)\b(?:[A-F0-9]{2})(?::[A-F0-9]{2}){6} - Cylian

2
它不会改变搜索过程,但它会影响找到匹配项后组的检索。
例如: 文本: text = 'John Wick'
要查找的模式: regex = re.compile(r'John(?:\sWick)') # 这里我们正在寻找'John'以及一个组(空格+Wick)。?:使这个组无法检索。
当我们打印匹配项时-没有任何变化: <re.Match object; span=(0, 9), match='John Wick'>
但是,如果您尝试使用(?:)语法手动访问该组: res = regex.finditer(text) for i in res: print(i) print(i.group(1)) # 这里我们正在尝试检索(?:\sWick)组
它会给我们一个错误: IndexError: no such group 另外,请看: Python文档: (?:...) 正则表达式圆括号的非捕获版本。与括号内的任何正则表达式匹配,但是在执行匹配或稍后在模式中引用后,无法检索由该组匹配的子字符串。
在文档中指向re页面的链接: https://docs.python.org/3/library/re.html

0

(?:...) 表示一个非捕获组。该组不会被捕获。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接