2011-08-19 44 views
5

我有以下文字:檢索內部#{}文字

#{king} for a ##{day}, ##{fool} for a #{lifetime} 

而下面的(碎)的正則表達式:

[^#]#{[a-z]+} 

我想匹配所有#{字}而不是# #{words}(加倍'#'就像轉義一樣)。

今天我注意到,我有的正則表達式忽略了第一個單詞(拒絕匹配#{king},但正確地忽略了## {day}和## {fool})。

>>> regex = re.compile("[^#]#{[a-z]+}") 
>>> regex.findall(string) 
[u' #{lifetime}'] 

有關如何改進當前正則表達式以適應我的需求的任何建議? 我想這個問題是[^#] ...

回答

6

你必須使用 「負向後斷言」正確的正則表達式應該是這樣的:

import re 
t = "#{king} for a ##{day}, ##{fool} for a #{lifetime}" 
re.findall(r'(?<!#)#{([a-z]+)}', t) 

返回

['king', 'lifetime'] 

說明:

(?<!prefix)pattern表達式匹配pattern只有當它不是由prefix preceeded。

+0

你的解決方案更好,我忘記了負面的後顧之憂。 – grep

+0

很酷的功能?這是蟒蛇正則表達式具體? –

+0

@Andrei,不,它似乎不是python特有的(根據[this site](http://www.regular-expressions.info/lookaround.html)),但他們說:「像JavaScript,Ruby和Tcl這樣的風格可以做盡管它們確實支持lookahead,但根本不支持lookbehind。「 – MatToufoutu

0

試試這個:

re.compile('^#\{[\w]+\}') 
+1

你試過了嗎?它僅匹配'#{king}',但不匹配'#{lifetime}'。 – hughdbrown

+0

我改正了它,它現在應該工作 – prince

2

使用回顧後建設:

>>> s='#{king} for a ##{day}, ##{fool} for a #{lifetime}' 
>>> r=re.compile(r'(?:^|(?<=[^#]))#{\w+}') 
>>> r.findall(s) 
['#{king}', '#{lifetime}'] 
>>> 
2
>>> regex = re.compile("(?:^|[^#])#{[a-z]+}") 
>>> regex.findall(string) 
['#{king}', ' #{lifetime}'] 
>>> 
+1

值得注意的是,這個解決方案的問題(不使用否定後置斷言)是不適用於'#{king}#{blah}' - 'findall'返回非重疊匹配。 –

1

將其替換爲(?:^|[^#])。就像你推斷的那樣,只有[^#]表示一個不是#的字符,這顯然沒有在行首。