2017-08-04 45 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 --| 

此外,它是使用原始字符串字面量爲正則表達式的聲明,只是爲了避免進一步的誤會時加字邊界或反向引用的最佳實踐。

相關問題