2017-08-04 109 views
1

我不明白为什么两个后续代码块会给测试用例提供不同的结果。第一个代码块按预期返回2016年,但是当进行小改动时,第二个返回None。Python 3的正则表达式返回意外的结果

这里是第一位的,它返回 '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。请注意,组(1)和组(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?

+2

第一个片段返回一年。请参阅https://ideone.com/1v7FQe。第二个片段[返回None](https://ideone.com/BWIkcq),因为第三组不匹配。你最终的目标是什么?回归年?然后[在第二个片段中使用'.group(4)'](https://ideone.com/6qT6Jr)。 –

+0

为什么第三组不匹配?不会\ 2016年匹配吗? – jss367

+1

但是'(uary)?'*是**捕获**组,并且它被分配ID = 3(因为它是模式中的第三个捕获组)。 '(\ d {2,4})'是第四组。 –

回答

5

由于第二正则表达式中包含一个额外(uary)?捕捉组,比赛结果现在包含4组,.group(3)不再映射到一年,但到可选uary子。并且由于Jan之后的输入没有uary,所以组值为,它刚刚未初始化。

最好的方式来增加可选的群体,同时保持组结构完好通过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 --| 

此外,它是使用原始字符串字面量为正则表达式的声明,只是为了避免进一步的误会时加字边界或反向引用的最佳实践。

相关问题