Skip to main content
 首页 » 编程设计

返回意外结果的 Python 3 正则表达式

2025年05月04日30myhome

我不明白为什么后面的两个代码块会为测试用例提供不同的结果。第一个代码块按预期返回 2016,但当进行小的更改时,第二个代码块返回 None。

这是第一个,按预期返回“2016”

import re 
date = '24 Jan 2016' 
def func(line): 
    month_regex = re.search('(\d{1,2})\s(Jan)\s(\d{2,4})', line) 
    if month_regex: 
        year = month_regex.group(3) 
    return year 
func(date) 

然后,我添加“(uary)?”到正则表达式,由于某种原因,它返回 None。请注意,group(1) 和 group(2) 在这两种情况下的结果相同。

import re 
date = '24 Jan 2016' 
def func(line): 
    month_regex = re.search('(\d{1,2})\s(Jan(uary)?)\s(\d{2,4})', line) 
    if month_regex: 
        year = month_regex.group(3) 
    return year 
func(date) 

为什么第二个代码块返回 None?

请您参考如下方法:

由于第二个正则表达式包含一个额外的 (uary)? capturing 组,匹配结果现在包含 4 个组和 .group(3) 不再映射到年份,而是映射到可选的 uary 子字符串。并且由于输入在 Jan 之后没有 uary,因此组值为 None,它只是未初始化。

在保持组结构不变的同时添加可选组的最佳方法是通过 non-capturing groups :

month_regex = re.search(r'(\d{1,2})\s(Jan(?:uary)?)\s(\d{2,4})', line) 
                                         ^^  

参见 Python demo online .

这里,分组如下:

(\d{1,2})\s(Jan(?:uary)?)\s(\d{2,4}) 
|-- 1 --|  |---- 2 -----|  |-- 3 --| 

此外,最佳做法是使用原始字符串文字进行正则表达式模式声明,只是为了避免在添加单词边界或反向引用时产生进一步的误解。