2017-08-15 39 views
13

我正在寫一個函數來從Python中的文本中拆分數字和其他一些東西。該代碼看起來是這樣的:Python 2和3're.sub'不一致

EN_EXTRACT_REGEX = '([a-zA-Z]+)' 
NUM_EXTRACT_REGEX = '([0-9]+)' 
AGGR_REGEX = EN_EXTRACT_REGEX + '|' + NUM_EXTRACT_REGEX 

entry = re.sub(AGGR_REGEX, r' \1\2', entry) 

現在,這個代碼在python3完全正常,但它不會在python2工作,並得到一個「無與倫比組」的錯誤。

問題是,我需要支持這兩個版本,我不能讓它在python2中正常工作,儘管我嘗試了各種其他方式。

我很好奇什麼可能是這個問題的根源,是否有任何解決方法?

回答

10

我認爲這個問題可能是正則表達式模式匹配的子模式EN_EXTRACT_REGEXNUM_EXTRACT_REGEX,但不能同時的一個其他。

re.sub()與第一個模式中的字母字符相匹配時,它將嘗試替換第二個組參考\2,因爲只有第一個組匹配 - 第二個組沒有匹配。

類似地,當數字模式匹配時,沒有\1組進行替換,所以這也失敗了。

你可以看到,這是與該測試在Python 2的情況下:

>>> re.sub(AGGR_REGEX, r' \1', 'abcd') # reference first pattern 
abcd 
>>> re.sub(AGGR_REGEX, r' \2', 'abcd') # reference second pattern 
Traceback (most recent call last): 
.... 
sre_constants.error: unmatched group 

的區別在於必須爲Python 2和Python 3的不同版本的正則表達式引擎的內部可惜我不能提供一個明確的理由不同,但是,有在3.5版本中關於無法比擬的一組記錄變化爲re.sub()

改變在3.5版本:無與倫比組與空字符串替換。

它解釋了爲什麼它在Python> = 3.5中工作,但不在早期版本中:基本忽略不匹配的組。


作爲一種變通方法,你可以改變你的模式來處理兩場比賽作爲一個組:

import re 

EN_EXTRACT_REGEX = '[a-zA-Z]+' 
NUM_EXTRACT_REGEX = '[0-9]+' 
AGGR_REGEX = '(' + EN_EXTRACT_REGEX + '|' + NUM_EXTRACT_REGEX + ')' 
# ([a-zA-Z]+|[0-9]+) 

for s in '', '1234', 'abcd', 'a1b2c3', 'aa__bb__1122cdef', '_**_': 
    print(re.sub(AGGR_REGEX, r' \1', s)) 

輸出

 

1234 
abcd 
a 1 b 2 c 3 
aa__ bb__ 1122 cdef 
_**_ 
+0

謝謝,這個效果很好的兩個版本。 :) –