#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
def lreplace(s, old, new):
"""Return a copy of string `s` with leading occurrences of
substring `old` replaced by `new`.
>>> lreplace('abcabcdefabc', 'abc', 'X')
'XXdefabc'
>>> lreplace('_abc', 'abc', 'X')
'_abc'
>>> print lreplace('☃☃_[☃]_☃', '☃', 'SM')
SMSM_[☃]_☃
"""
return re.sub(r'^(?:%s)+' % re.escape(old),
lambda m: new * (m.end() // len(old)),
s)
def replaceLeadingString(string, old, new = ''):
# http://stackoverflow.com/q/4649997
n = 0
o = 0
s = len(old)
while string.startswith(old, o):
n += 1
o += s
return new * n + string[o:]
#from profilestats import profile
#@profile
def test(n):
for _ in xrange(n):
old, new = 'префикс', 'abc'
for s in [old*2 +'остаток',
'no'+old,
old,
old*2,
new+new,
'xx\n'+old,
]:
args = s, old, new
assert lreplace(*args) == replaceLeadingString(*args)
if __name__=="__main__":
import cProfile
cProfile.run('test(10**4)')
IyEvdXNyL2Jpbi9lbnYgcHl0aG9uCiMgLSotIGNvZGluZzogdXRmLTggLSotCmltcG9ydCByZQoKZGVmIGxyZXBsYWNlKHMsIG9sZCwgbmV3KToKICAgICIiIlJldHVybiBhIGNvcHkgb2Ygc3RyaW5nIGBzYCB3aXRoIGxlYWRpbmcgb2NjdXJyZW5jZXMgb2YKICAgIHN1YnN0cmluZyBgb2xkYCByZXBsYWNlZCBieSBgbmV3YC4KCiAgICA+Pj4gbHJlcGxhY2UoJ2FiY2FiY2RlZmFiYycsICdhYmMnLCAnWCcpCiAgICAnWFhkZWZhYmMnCiAgICA+Pj4gbHJlcGxhY2UoJ19hYmMnLCAnYWJjJywgJ1gnKQogICAgJ19hYmMnCiAgICA+Pj4gcHJpbnQgbHJlcGxhY2UoJ+KYg+KYg19b4piDXV/imIMnLCAn4piDJywgJ1NNJykKICAgIFNNU01fW+KYg11f4piDCiAgICAiIiIKICAgIHJldHVybiByZS5zdWIocideKD86JXMpKycgJSByZS5lc2NhcGUob2xkKSwKICAgICAgICAgICAgICAgICAgbGFtYmRhIG06IG5ldyAqIChtLmVuZCgpIC8vIGxlbihvbGQpKSwKICAgICAgICAgICAgICAgICAgcykKCmRlZiByZXBsYWNlTGVhZGluZ1N0cmluZyhzdHJpbmcsIG9sZCwgbmV3ID0gJycpOgogICAgIyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcS80NjQ5OTk3CiAgICBuID0gMAogICAgbyA9IDAKICAgIHMgPSBsZW4ob2xkKQoKICAgIHdoaWxlIHN0cmluZy5zdGFydHN3aXRoKG9sZCwgbyk6CiAgICAgICAgbiArPSAxCiAgICAgICAgbyArPSBzCgogICAgcmV0dXJuIG5ldyAqIG4gKyBzdHJpbmdbbzpdCgojZnJvbSBwcm9maWxlc3RhdHMgaW1wb3J0IHByb2ZpbGUKI0Bwcm9maWxlCmRlZiB0ZXN0KG4pOgogICAgZm9yIF8gaW4geHJhbmdlKG4pOgogICAgICAgIG9sZCwgbmV3ID0gJ9C/0YDQtdGE0LjQutGBJywgJ2FiYycKICAgICAgICBmb3IgcyBpbiBbb2xkKjIgKyfQvtGB0YLQsNGC0L7QuicsCiAgICAgICAgICAgICAgICAgICdubycrb2xkLAogICAgICAgICAgICAgICAgICBvbGQsCiAgICAgICAgICAgICAgICAgIG9sZCoyLAogICAgICAgICAgICAgICAgICBuZXcrbmV3LAogICAgICAgICAgICAgICAgICAneHhcbicrb2xkLAogICAgICAgICAgICAgICAgICBdOgogICAgICAgICAgICBhcmdzID0gcywgb2xkLCBuZXcKICAgICAgICAgICAgYXNzZXJ0IGxyZXBsYWNlKCphcmdzKSA9PSByZXBsYWNlTGVhZGluZ1N0cmluZygqYXJncykKICAgIAppZiBfX25hbWVfXz09Il9fbWFpbl9fIjoKICAgIGltcG9ydCBjUHJvZmlsZQogICAgY1Byb2ZpbGUucnVuKCd0ZXN0KDEwKio0KScpCgo=