2014-09-03 52 views
3

我正在寫一個正則表達式來匹配電話號碼。我遇到的其中一個問題是一些郵編看起來像電話號碼。例如,在巴西,郵政編碼是這樣的:Python的正則表達式負向lookbehind沒有失敗的匹配

30.160-0131 

因此,一個簡單的正則表達式將捕捉他們爲誤報:

In [63]: re.search(r"(?P<phone>\d+\.\d+-\d+)", "30.160-0131") 
Out[63]: <_sre.SRE_Match at 0x102150990> 

幸運的是,這樣的郵政編碼往往帶有前綴這通常意味着「郵政編碼」是這樣的:

CEP 30.160-0131 

所以,如果你看到CEP中的東西,看起來像一個電話號碼前,那麼它是不是一個電話號碼 - 這是一個郵政編碼。我一直在試圖編寫一個正則表達式來捕獲使用negative lookbehind,但它不工作。它仍然匹配:

In [62]: re.search(r"(?<!CEP)(\d+\.\d+-\d+)", "CEP 30.160-0131") 
Out[62]: <_sre.SRE_Match at 0x102150eb8> 

爲什麼它仍然匹配,我怎麼能得到消極的後視失敗的比賽?

+1

因爲它的一部分*可以匹配:http://regex101.com/r/aU4fV4/1 – jonrsharpe 2014-09-03 07:16:48

回答

1

可避免負面向前看符號,如果你讓那些郵政編碼的匹配,並且仍然只提取電話號碼:

m = re.search(r"CEP \d+\.\d+-\d+|(\d+\.\d+-\d+)", s) 

然後檢查您的電話號碼是否在m.group(1)之內。


小演示與re.findall

>>> import re 
>>> s = "There is a CEP 30.160-0131 and a 30.160-0132 in that sentence, which repeats itself like there is a CEP 30.160-0131 and a 30.160-0132 in that sentence." 
>>> m = re.findall(r"CEP \d+\.\d+-\d+|(\d+\.\d+-\d+)", s) 
>>> print(m) 
['', '30.160-0132', '', '30.160-0132'] 

從那裏,你可以過濾掉空字符串。

+1

@misha在通常使用的代碼中無法使用lookbehind有助於此;) – Jerry 2014-09-03 07:34:59

2

表達式匹配,因爲你沒有做任何事情來錨定數字。例如:

"CEP 11.213-132" 

將匹配1.213-132,因爲它沒有緊跟CEP。但是,你可以強制一個空白,或線錨的開始,是第一位的前面:

re.search(r"(?<!CEP)(?:\s+|^)(\d+\.\d+-\d+)", s) 
+0

但是,如果沒有前綴(例如, 're.search(r「(?<!CEP)\ s +(\ d + \。\ d + - \ d +)」,「30.160-0131」)'將返回'None'。 – misha 2014-09-03 07:22:18

+1

@misha,對,請嘗試更新的表達式 – perreal 2014-09-03 07:25:01

+0

謝謝!你的解決方案運行良好,但是我最終用@Jerry的想法去做,因爲它更簡單,更容易理解。 – misha 2014-09-04 07:27:20

相關問題