2014-05-22 22 views
2

我認爲我對RegEx非常滿意,以至於我可以閱讀最多的任何一篇,但是這個簡單的(用Python)讓我感到莫名其妙。 www.regexpal.com給出了與iPython不同的結果。這是Python正則表達式中的錯誤嗎?

data = 'four year entrepreneurial program. Students develop and run a business, gain much needed ...' 

m = re.compile('entrepreneur|business\s(plan|model)') 

m.findall(data) 

['']

怎麼可能吧?如果我換用括號括住了整個事情,它工作得更好,但仍然會返回一個空字符串作爲匹配:

m = re.compile('(entrepreneur|business\s(plan|model))') 

m.findall(data) 

[('entrepreneur', '')]

正如我所說的,第一個適用於www.regexpal.com。我還用Python(而不是iPython)測試了它,並且也在那裏失敗。

+1

你期望找到什麼,爲什麼? – jgritty

+0

請注意,如果您將其與regexpal進行比較,您應該使用're.match'或're.search'.m.search(data).group()' - >''entrepreneur'' –

+1

'.findall'正如預期的那樣工作:*返回字符串中所有不重疊匹配的列表*由於在第一個「企業家」不在一個組中,它不會被'.findall'返回。 –

回答

3

findall收集組的值。它不會返回整個匹配的子字符串。您的模式

entrepreneur|business\s(plan|model) 

循環遍歷數據字符串,直到找到匹配。一旦找到匹配項(此處爲entrepreneurial program...),它將停在那裏並捕獲第一個組的值(它是空的)。然後它進一步運行,但沒有找到任何匹配。所以最終的結果是一個空字符串的列表。

觀察類似regexpal行爲,加上括號整個表達式並進行其他組可選:

>>> re.findall(r'(entrepreneur|business\s(?:plan|model))', data) 
['entrepreneur'] 
+0

謝謝,好吧,這是有道理的。但是爲什麼[('企業家','')]如果我把所有的東西都包裝在parens中? '企業家'匹配第一名,但沒有匹配第二名。那麼爲什麼這個''? – Brad

+0

@Brad:重新引擎無法匹配「無」。這總是一些東西(只要整場比賽取得成功)。 – georg

2

的問題是括號。他們創建了一個捕獲組,它與您的示例字符串無法匹配(取而代之,未分組的entrepreneur模式部分匹配)。 re.findall如果模式中有任何組,則返回捕獲組結果的元組,這就是爲什麼您要獲取空字符串。在代碼的第二個版本中,您有兩個組,第一個覆蓋整個模式,而第二個代碼僅覆蓋plan|model部分(不匹配)。

如果使用非捕獲組((?:X))爲plan|model交替,你可能會得到結果,你希望(文字"entrepreneur"),作爲re.findall如果沒有捕獲組返回整個匹配的文本。

嘗試:"entrepreneur|business\s(?:plan|model)"

2

這是捕獲組是如何與findall工作。

re.findall(pattern, string, flags=0)

返回所有非重疊的字符串模式的匹配,因爲字符串列表。字符串從左到右掃描,匹配結果爲 ,找到的順序返回。如果 模式中存在一個或多個組,請返回組列表;如果 模式具有多個組,則這將是元組列表。除非他們觸及另一場比賽的開始,否則空的比賽包含在 結果中。

您的交替的右手邊捕獲組,但交替的左手側的字符串相匹配。

entrepreneur|business\s(plan|model) 

Regular expression visualization

Debuggex Demo

因此,該集團是空的,因爲左側相匹配,而這正是的findall給你。

要解決,讓你組非捕獲:

entrepreneur|business\s(?:plan|model) 

現在,有沒有組,以便findall回報你的主要表現相匹配。