[英]Python regex module vs re module - pattern mismatch
如果遇到同樣的問題,請更新regex
模塊。
您需要2017.04.23
或更高版本。
(?i)\b((\w{1,3})(-|\.{2,10})[\t ]?)+(\2\w{2,})
正在使用regex
模塊...
import re # standard library
import regex # https://pypi.python.org/pypi/regex/
content = '"Erm....yes. T..T...Thank you for that."'
pattern = r"(?i)\b((\w{1,3})(-|\.{2,10})[\t ]?)+(\2\w{2,})"
substitute = r"\2-\4"
print(re.sub(pattern, substitute, content))
print(regex.sub(pattern, substitute, content))
輸出:
"Erm....yes. T-Thank you for that."
"-yes. T..T...Thank you for that."
問:如何我都要寫這個正則表達式來使regex
模塊反應,因此用同樣的方法re
模塊呢?
使用re
模塊不是一個選項,因為我需要具有動態長度的后視鏡。
澄清一下:如果正則表達式適用於兩個模塊會很好,但最后我只需要它用於regex
看來這個bug與回溯有關。 它在重復捕獲組時發生,並且捕獲組匹配但組之后的模式不匹配。
一個例子:
>>> regex.sub(r'(?:(\d{1,3})x)+', r'\1', '123x5')
'5'
作為參考,預期輸出將是:
>>> re.sub(r'(?:(\d{1,3})x)+', r'\1', '123x5')
'1235'
在第一次迭代中,捕獲組(\\d{1,3})
消耗前3位數, x
消耗以下“x”字符。 然后,由於+
,第二次嘗試匹配。 這次, (\\d{1,3})
匹配“5”,但x
無法匹配。 但是,捕獲組的值現在(重新)設置為空字符串而不是預期的123
。
作為解決方法,我們可以阻止捕獲組進行匹配。 在這種情況下,將其更改為(\\d{2,3})
足以繞過該錯誤(因為它不再匹配“5”):
>>> regex.sub(r'(?:(\d{2,3})x)+', r'\1', '123x5')
'1235'
至於有問題的模式,我們可以使用先行斷言; 我們將(\\w{1,3})
更改為(?=\\w{1,3}(?:-|\\.\\.))(\\w{1,3})
:
>>> pattern= r"(?i)\b((?=\w{1,3}(?:-|\.\.))(\w{1,3})(-|\.{2,10})[\t ]?)+(\2\w{2,})"
>>> regex.sub(pattern, substitute, content)
'"Erm....yes. T-Thank you for that."'
編輯 :現在在正則表達式2017.04.23中解決了該錯誤
剛剛在Python 3.6.1中測試過,原始模式在re
和regex
工作方式相同
原始解決方法 - 您可以使用惰性運算符+?
(即一個不同的正則表達式,其行為與原始模式不同,例如T...Tha....Thank
):
pattern = r"(?i)\b((\w{1,3})(-|\.{2,10})[\t ]?)+?(\2\w{2,})"
不成功的較長匹配會創建空的\\2
組,從概念上講,它應該觸發回溯到較短的匹配,其中嵌套組不為空,但regex
似乎“優化”並且不從頭開始計算較短的匹配,但使用一些緩存值,忘記撤消嵌套匹配組的更新。
貪婪匹配示例((\\w{1,3})(\\.{2,10})){1,3}
將首先嘗試3次重復,然后回溯到更少:
expected: 1,3 [('Erm....', 'Erm', '....'), ('T...', 'T', '...')]
actual: 1,3 [('Erm....', '', '....'), ('T...', '', '...')]
expected: 3 []
actual: 3 []
expected: 2 [('T...', 'T', '...')]
actual: 2 [('T...', 'T', '...')]
expected: 1 [('Erm....', 'Erm', '....'), ('T..', 'T', '..'), ('T...', 'T', '...')]
actual: 1 [('Erm....', 'Erm', '....'), ('T..', 'T', '..'), ('T...', 'T', '...')]
輸出:
expected: 1,3 [('Erm....', 'Erm', '....'), ('T...', 'T', '...')] actual: 1,3 [('Erm....', '', '....'), ('T...', '', '...')] expected: 3 [] actual: 3 [] expected: 2 [('T...', 'T', '...')] actual: 2 [('T...', 'T', '...')] expected: 1 [('Erm....', 'Erm', '....'), ('T..', 'T', '..'), ('T...', 'T', '...')] actual: 1 [('Erm....', 'Erm', '....'), ('T..', 'T', '..'), ('T...', 'T', '...')]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.