Другим вариантом является использование вида вперед s/.*?(?=$pattern)//xs
:
re.sub(r'(?s).*?(?=cat|dog|rat)', '', text, 1)
Путь без регулярных выражений:
for option in 'cat dog rat'.split():
index = text.find(option)
if index != -1: # found
text = text[index:]
break
Способ без регулярных выражений почти в 5 раз быстрее (для некоторого ввода):
$ python -mtimeit -s'from drop_until_word import drop_re, text, options;' \
> 'drop_re(text, options)'
1000 loops, best of 3: 1.06 msec per loop
$ python -mtimeit -s'from drop_until_word import drop_search, text, options;'\
> 'drop_search(text, options)'
10000 loops, best of 3: 184 usec per loop
$ python -mtimeit -s'from drop_until_word import drop_find, text, options;' \
> 'drop_find(text, options)'
1000 loops, best of 3: 207 usec per loop
Где drop_until_word.py
:
import re
def drop_re(text, options):
return re.sub(r'(?s).*?(?='+'|'.join(map(re.escape, options))+')', '',
text, 1)
def drop_re2(text, options):
return re.sub(r'(?s).*?('+'|'.join(map(re.escape, options))+')', '\\1',
text, 1)
def drop_search(text, options):
m = re.search('|'.join(map(re.escape, options)), text)
return text[m.start():] if m else text
def drop_find(text, options):
indexes = [i for i in (text.find(option) for option in options) if i != -1]
return text[min(indexes):] if indexes else text
text = open('/usr/share/dict/words').read()
options = 'cat dog rat'.split()
def test():
assert drop_find(text, options) == drop_re(text, options) \
== drop_re2(text, options) == drop_search(text, options)
txt = 'dog before cat'
r = txt
for f in [drop_find, drop_re, drop_re2, drop_search]:
assert r == f(txt, options), f.__name__
if __name__=="__main__":
test()