Sha*_*ank 10 python regex string split
使用该re
模块,似乎我无法拆分空字符串的模式匹配:
>>> re.split(r'(?<!foo)(?=bar)', 'foobarbarbazbar')
['foobarbarbazbar']
Run Code Online (Sandbox Code Playgroud)
换句话说,即使找到匹配项,如果它是空字符串,甚至re.split
也不能拆分字符串.
这些文档re.split
似乎支持我的结果.
对于这种特殊情况,"解决方法"很容易找到:
>>> re.sub(r'(?<!foo)(?=bar)', 'qux', 'foobarbarbazbar').split('qux')
['foobar', 'barbaz', 'bar']
Run Code Online (Sandbox Code Playgroud)
但这是一种容易出错的方法,因为那时我必须要注意已经包含我正在拆分的子字符串的字符串:
>>> re.sub(r'(?<!foo)(?=bar)', 'qux', 'foobarbarquxbar').split('qux')
['foobar', 'bar', '', 'bar']
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来分割与re
模块的空模式匹配?另外,为什么re.split
不允许我首先这样做呢?我知道其他分裂算法可以与正则表达式一起使用; 例如,我可以使用JavaScript的内置功能完成此操作String.prototype.split()
.
不幸的是,split
需要非零宽度匹配,但尚未修复,因为相当多的错误代码依赖于当前行为,例如使用[something]*
正则表达式.使用这样的模式现在将生成一个FutureWarning
和那些永远不能拆分的模式,ValueError
从Python 3.5开始抛出:
>>> 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.
Run Code Online (Sandbox Code Playgroud)
这个想法是,经过一段时间的警告后,可以改变行为,以便你的正则表达式再次起作用.
如果您无法使用该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'))
Run Code Online (Sandbox Code Playgroud)
如果您确定匹配仅为零宽度,则可以使用拆分的开头来获得更简单的代码:
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'))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4519 次 |
最近记录: |