簡體   English   中英

Python正則表達式:拆分為空字符串的模式匹配

[英]Python regex: splitting on pattern match that is an empty string

使用re模塊,看來我無法拆分為空字符串的模式匹配:

>>> re.split(r'(?<!foo)(?=bar)', 'foobarbarbazbar')
['foobarbarbazbar']

換句話說,即使找到匹配項,即使它是空字符串,即使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()做到這一點。

不幸的是, split需要一個非零寬度的匹配,但尚未解決,因為相當多的不正確代碼取決於當前行為,例如使用[something]*作為正則表達式。 現在,使用此類模式將生成FutureWarning而那些永遠無法拆分的模式將從Python 3.5開始拋出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模塊, regex可以使用re.finditer()編寫自己的split函數:

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'))
import regex
x="bazbarbarfoobar"
print regex.split(r"(?<!baz)(?=bar)",x,flags=regex.VERSION1)

您可以在這里使用regex模塊。

要么

(.+?(?<!foo))(?=bar|$)|(.+?foo)$

使用re.findall

觀看演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM