2017-08-04 17 views
1

2つのフォローコードブロックがテストケースで異なる結果をもたらす理由はわかりません。最初のコードブロックは期待通りに2016を返しますが、小さな変更を加えると2番目のコードブロックはNoneを返します。予期しない結果を返すPython 3の正規表現

ここで、 "(uary)?" 私は追加し、その後

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) 

を期待通りに '2016' を返す最初のもの、です正規表現に何らかの理由で、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) 

なぜ2番目のコードブロックがNoneを返すのですか?

+2

最初のスニペットは年を返します。 https://ideone.com/1v7FQeを参照してください。 3番目のグループが一致しなかったため、2番目のスニペット([None')](https://ideone.com/BWIkcq)が返されます。あなたの最終目標は何ですか?年を返す?それから[2番目のスニペットで '.group(4)'を使う](https://ideone.com/6qT6Jr)。 –

+0

3番目のグループが一致しないのはなぜですか? \ d {2,4}は2016にマッチしませんか? – jss367

+1

しかし、 '(uary)?' *は**キャプチャ**グループであり、ID = 3(パターンの3番目のキャプチャグループなので)に割り当てられます。 '(\ d {2,4})'は第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 --| 

、あなたが単語の境界や後方参照を追加したときにだけ、さらに誤解を避けるために、正規表現パターン宣言のために、生の文字列リテラルを使用することをお勧めします。

関連する問題