There are several useful ways to handle multiple string replacement at the same time in python. However, I am unable to create an efficient function that can do this, as well as support backlinks.
I would like to use a dictionary of expression / replacement terms, where replacement terms may contain backlinks to something matched by the expression.
eg. (pay attention to \ 1)
repdict = {'&&':'and', '||':'or', '!([a-zA-Z_])':'not \1'}
I put the SO answer, mentioned at the beginning, in the function below, which is great for expression / replacement pairs that don't contain backlinks:
def replaceAll(repdict, text):
repdict = dict((re.escape(k), v) for k, v in repdict.items())
pattern = re.compile("|".join(repdict.keys()))
return pattern.sub(lambda m: repdict[re.escape(m.group(0))], text)
However, it does not work for a key that contains a backlink.
>>> replaceAll(repldict, "!newData.exists() || newData.val().length == 1")
'!newData.exists() or newData.val().length == 1'
If I do it manually, it works fine. eg:.
pattern = re.compile("!([a-zA-Z_])")
pattern.sub(r'not \1', '!newData.exists()')
Works as expected:
'not newData.exists()'
, , , backref, -.
. , backrefs , replacer:
def replaceAll(repPat, text):
def replacer(obj):
match = obj.group(0)
if match[:1] == "!": return 'not ' + match[1:]
else: return repPat[naive_escaper(match)]
pattern = re.compile("|".join(repPat.keys()))
return pattern.sub(replacer, text)
def naive_escaper(string):
if '=' in string: return string.replace('=', '\=')
elif '|' in string: return string.replace('|', '\|')
else: return string
repPat = {'!([a-zA-Z_])':'', '&&':'and', '\|\|':'or', '\=\=\=':'=='}
replaceAll(repPat, "(!this && !that) || !this && foo === bar")
:
'(not this and not that) or not this'
, - , , , .