2010-04-26 102 views
16

一個在Python(否則很強大)re模塊的特殊怪癖是re.split()will never split a string on a zero-length match,例如,如果我想分割沿字邊界的字符串:爲什麼Python的`re.split()`在零長度匹配上分裂?

>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!") 
['Split', 'along', 'words,', 'preserve', 'punctuation!'] 

,而不是

['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!'] 

爲什麼它有這個限制?它是否由設計?其他正則表達式的風格是這樣嗎?

回答

22

這是一個設計決定,而且可能無論如何。蒂姆·彼得斯提出this post解釋:

例如,如果你在模式X *拆分「ABC」,你有什麼期待 ?該模式匹配(長度爲0)4處, 但我敢打賭,大多數人會驚訝地獲得

[ '', 'A', 'B', 'C', '']

背部,而不是(因爲他們得到)

[ 'ABC']

有些人他雖然不同意。由於向後兼容性問題,Guido van Rossum doesn't want it changed。他沒有say

我很好,添加一個標誌來啓用此行爲。

編輯

有張貼由Jan Burgy一個workaround

>>> s = "Split along words, preserve punctuation!" 
>>> re.sub(r"\s+|\b", '\f', s).split('\f') 
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!'] 

'\f'可以通過任何未使用的字符來代替。

+0

感謝您的鏈接和解決方法。我真的認爲他們應該接受BDFL的建議併爲此添加一個標誌。 – 2010-04-26 12:25:58

+0

這是一個真正蹩腳的設計決定。 RE是一個設計決策不應該被人們「期望」驅動的事情,因爲很多關於RE的事情都不符合人們的「期望」,無論如何這意味着什麼。 'x *'應該與''abc'匹配,因爲這就是RE所說的:「匹配x,零次或多次」。這就是你使用'*'時得到的結果。 – 2013-02-22 21:01:11

+0

當試圖分割一個pascal大小寫變量名('re.split('(?<= [a-z])(?= [A-Z])',name)')時,也碰到過這個問題。太糟糕了。 – Blixt 2015-05-05 14:53:59

0

基本上,split()是兩個不同的函數合成一個。如果您提供參數,它的行爲與沒有參數時的行爲非常不同。

起初,它會似乎

s.split() == s.split(' \t\n') 

但這種情況並非如此,因爲你表現出來了。 的醫生說:

[...] 如果不指定SEP是或無,任何空白字符串 是一個分離器和空字符串從結果中刪除。 [...]

即使添加'remove_empty'參數,它仍會表現怪異,因爲'remove_empty'的默認取決於'sep'參數的存在。

+0

我想你錯了'.split()' - 我指的是're.split()',而不是字符串方法。 – 2010-04-30 16:29:05

+0

啊,當然:-) – 2010-04-30 17:42:43

1

要解決這個問題,你可以使用regex package這使得該VERSION1模式split()產生零長度匹配以及

>>> import regex as re 
>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!", flags=re.V1) 
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!'] 
相關問題