使用该re模块,似乎无法拆分为空字符串的模式匹配:
re
>>> re.split(r'(?<!foo)(?=bar)', 'foobarbarbazbar') ['foobarbarbazbar']
换句话说,即使找到匹配项,即使它是空字符串,re.split也无法拆分该字符串。
re.split
的文档re.split似乎支持我的结果。
对于这种特殊情况,很容易找到“解决方法”:
>>> re.sub(r'(?<!foo)(?=bar)', 'qux', 'foobarbarbazbar').split('qux') ['foobar', 'barbaz', 'bar']
但这是一种容易出错的方法,因为这样我就必须提防已经包含要分割的子字符串的字符串:
>>> re.sub(r'(?<!foo)(?=bar)', 'qux', 'foobarbarquxbar').split('qux') ['foobar', 'bar', '', 'bar']
有没有更好的方法可以拆分与re模块的空模式匹配?另外,为什么re.split不允许我首先这样做呢?我知道使用正则表达式的其他拆分算法是可行的。例如,我可以使用JavaScript的内置功能做到这一点String.prototype.split()。
String.prototype.split()
不幸的是,split要求非零宽度匹配,但尚未解决,因为很多不正确的代码都依赖于当前行为,例如使用[something]*正则表达式。现在,使用此类模式会生成,FutureWarning而那些 永远 无法拆分的模式会ValueError从Python 3.5开始抛出:
split
[something]*
FutureWarning
ValueError
>>> re.split(r'(?<!foo)(?=bar)', 'foobarbarbazbar') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.6/re.py", line 212, in split return _compile(pattern, flags).split(string, maxsplit) ValueError: split() requires a non-empty pattern match.
这个想法是,在一定时间的警告后,可以更改行为,以便您的正则表达式将再次起作用。
如果您不能使用该regex模块,则可以使用以下代码编写自己的split函数re.finditer():
regex
re.finditer()
def megasplit(pattern, string): splits = list((m.start(), m.end()) for m in re.finditer(pattern, string)) starts = [0] + [i[1] for i in splits] ends = [i[0] for i in splits] + [len(string)] return [string[start:end] for start, end in zip(starts, ends)] print(megasplit(r'(?<!foo)(?=bar)', 'foobarbarbazbar')) print(megasplit(r'o', 'foobarbarbazbar'))
如果您确定匹配项仅是零宽度,则可以使用分割的开头来获得更简单的代码:
import re def zerowidthsplit(pattern, string): splits = list(m.start() for m in re.finditer(pattern, string)) starts = [0] + splits ends = splits + [ len(string) ] return [string[start:end] for start, end in zip(starts, ends)] print(zerowidthsplit(r'(?<!foo)(?=bar)', 'foobarbarbazbar'))