2014-04-21 23 views
1

我試圖通過pattern.findall匹配字符串中的所有模式,但它僅適用部分re.Pattern.findall工作錯誤

代碼

#--coding:UTF-8 -- 
import re 
import pprint 
regex = r"(19|20|21)\d{2}" 
text = "1912 2013 2134" 
def main(): 
    pattern = re.compile(regex) 
    print pattern.findall(text) 

if __name__ == '__main__': 
    main() 

,並打印:

['19', '20', '21'] 

應該打印['1912', '2013','2134']

回答

3

re.findall docs,

如果模式中存在一個或多個組,返回組列表;如果模式有多個組,這將是一個元組列表。

由於您的原始正則表達式有一個捕獲組((19|20|21)),因此單獨捕獲的值已返回。你可以這樣

regex = r"(19|20|21)(\d{2})" 

與發揮現在我們有兩個捕獲組((19|20|21)(\d{2}))。那麼結果將是

[('19', '12'), ('20', '13'), ('21', '34')] 

爲了解決這個問題,你可以使用non-capturing group,這樣

regex = r"(?:19|20|21)\d{2}" 

這給下面的輸出

['1912', '2013', '2134'] 
+0

thx!但我必須問爲什麼它的作品。 – ssj

+0

@我已經將非捕獲組進行了精美的解釋。請檢查一次。 – thefourtheye

+0

我已經知道了你的想法,如果'findall'用於匹配組,它只會匹配組中的所有內容。所以如果我嘗試'((19 | 20 | 21)\ d {2})',結果將會是'[('1912','19'),('2013','20'),('2134 ','21')]' – ssj

1

回合括號表示匹配組。在您正則表達式,你正在尋找兩位數的號碼都要麼19,20或21

也許你需要這個表達式:

r'19\d{2}|20\d{2}|21\d{2}' 

這看起來對於任何編號開始的19後跟兩位數字或20後面跟着兩位數字,或者後面跟着兩位數字。

演示:

In [1]: import re 
In [2]: regex =rr'19\d{2}|20\d{2}|21\d{2}' 
In [3]: text = "1912 2013 2134" 
In [4]: pattern = re.compile(regex) 
In [5]: pattern.findall(text) 
Out[5]: ['1912', '2013', '2134'] 
+0

你只有兩個元素。所以,不需要使用範圍。 – thefourtheye

+0

@thefourtheye同意。它是無關的。 – shaktimaan

+1

難道這不符合以10,11,29等開頭的東西嗎? – Leigh

0

另一種選擇是從findall()剋制,而是做

print [i.group(0) for i in pattern.finditer(text)] 

finditer()給你一個迭代生產Match對象。他們可以查詢每場比賽的屬性。

另一種解決方案對於正則表達式能夠做什麼更優雅,但是這種方法更加靈活,因爲您沒有關於應該返回的組的隱含假設。