2015-07-20 71 views
0

我想獲得字符串10M5D8P成詞典:Python的正則表達式:回顧後先行+與字符集

L:10,d:5,P:8等等...

字符串可能但它始終是一個數字,後面跟着這個字母表中的單個字母:MIDNSHP = X

作爲第一步,我希望將字符串拆分爲lookbehead和lookahead,在兩種情況下匹配此正則表達式:[0- 9] + [MIDNSHP = X]

所以我不工作的解決方案看起來像這樣此刻:

import re

re.compile(「(? (?= [0-9] + [MIDNSHP = X])「)。split(」10M5D8P「)

它給我一個錯誤消息,不明白:「回顧後需要固定寬度模式」

回答

2

您可以使用re.findall

>>> import re 
>>> s = "10M5D8P" 
>>> {i[-1]:i[:-1] for i in re.findall(r'[0-9]+[MIDNSHP=X]', s)} 
{'M': '10', 'P': '8', 'D': '5'} 
>>> {i[-1]:int(i[:-1]) for i in re.findall(r'[0-9]+[MIDNSHP=X]', s)} 
{'M': 10, 'P': 8, 'D': 5} 

你的正則表達式是行不通的,因爲re模塊不支持可變長度後向斷言。而且它也不支持在零寬邊界上分割,所以這個(?<=\d)(?=[A-Z])也不可能。

+0

這是一個很好的解決方案,謝謝!但是我仍然很好奇爲什麼我的工作不行......? – user3182532

+0

參考此[回覆](http://stackoverflow.com/a/23782359/3451543):Python re模塊,因爲大多數語言(具有.NET的顯着例外),不支持可變長度lookbehind。 – mrorno

+0

有關您的解決方案的問題:如果我說myregex = re.compile(「[0-9] + [MIDNSHP = X]」),爲什麼它不再工作,並將其作爲re.findall的第一個參數? – user3182532

2

look-behind requires fixed-width pattern意思就是它所說的 - 一個隱藏式模式必須匹配Python引擎中固定數量的字符。特別是,不允許包含任何量詞(?,+,*)。因此,我們應該選擇一個固定寬度的一塊作爲我們回顧後使用:

(?<=[MIDNSHP=X])(?=\d) 

這僅使用單個字符作爲回顧後和一位數字爲超前。但是,如果您嘗試使用split這個表達式,它將因Python bug 3262而失敗。你需要使用這樣的替代方法:

>>> re.compile(r"(?<=[MIDNSHP=X])(?=\d)").sub('|', '10M5D8P').split("|") 
['10M', '5D', '8P'] 

但這是非常醜陋的。一個簡單的辦法是使用findall提取你想要什麼

>>> re.findall('([0-9]+)([MIDNSHP=X])', '10M5D8P') 
[('10', 'M'), ('5', 'D'), ('8', 'P')] 

,你可以很容易地創建一個字典,從其中:

>>> {k:int(v) for v,k in re.findall('([0-9]+)([MIDNSHP=X])', '10M5D8P')} 
{'P': 8, 'M': 10, 'D': 5} 
+0

我也喜歡這個,因爲它更通用,即捕獲允許具有不同長度的標識符(例如,10CG80M10GHJ)(儘管這在我的情況下不需要,但也許我將來需要這樣做) – user3182532