为什么Python的`re.split()`在零长度匹配上不分裂?

时间:2010-04-26 11:34:25

标签: python regex

Python中(非常强大的)re模块的一个特殊怪癖是re.split() will never split a string on a zero-length match,例如,如果我想沿着字边界分割字符串:

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

而不是

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

为什么会出现这种限制?它是按设计的吗?其他正则表达式的行为是这样的吗?

4 个答案:

答案 0 :(得分: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'可以替换为任何未使用的字符。

答案 1 :(得分:2)

要解决此问题,您可以使用regex packageVERSION1模式,这样split() 也会产生零长度匹配

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

答案 2 :(得分:0)

基本上,split()是两个不同的功能合二为一。如果您提供参数,则其行为与没有参数时调用的行为非常不同。

起初,似乎

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

但事实并非如此,正如您所示。 医生说:

[...] 如果未指定sep或为None,则为任何空白字符串 是一个分隔符,从结果中删除空字符串。 [...]

即使添加'remove_empty'参数,它仍然会表现得很奇怪,因为'remove_empty'的默认值取决于那里的'sep'参数。

答案 3 :(得分:0)

Python自3.7开始支持此功能:

>>> s = "You! Are you Tom? I am Danny."
>>> re.split(r'(?<=[.!\?])', s)
['You!', ' Are you Tom?', ' I am Danny.', '']