Reputation: 351
I am using the code below to find any words enclosed by "<<" and ">>" in a string and replace them with the relevant previously defined variable. This works, but is there a safer or more efficient way to accomplish this? I have seen several warnings about the use of eval, and my solution seems overly complicated.
import re
aa = 'alpha'
bb = 'beta'
cc = 'gamma'
teststr = 'A for <<aa>>, b means <<bb>>, and c could be <<cc>>.'
matches = re.finditer('<<(\w*)>>', teststr)
for i in matches:
teststr = teststr.replace(i.group(0), eval(i.group(1)) )
print teststr
Upvotes: 0
Views: 7688
Reputation: 89557
Use a dictionary and a lambda function as replacement:
>>> import re
>>> teststr = 'A for <<aa>>, b means <<bb>>, and c could be <<cc>>.'
>>> dico = { 'aa':'alpha', 'bb':'beta', 'cc':'gamma' }
>>> re.sub(r'<<([^>]*)>>', lambda m: dico[m.group(1)], teststr)
'A for alpha, b means beta, and c could be gamma.'
If you are not sure that each string between <<
and >>
exists as key in the dictionary, change [^>]*
to an alternation with all available keys: aa|bb|cc
. If you have to many keys and you don't want to make it by hand, you can build the pattern dynamically like this:
python 2.7:
>>> re.sub(r'<<(%s)>>'%"|".join(sorted(dico.keys(), reverse=True)), lambda x: dico[x.group(1)], teststr)
python 3.x:
>>> re.sub(r'<<({})>>'.format("|".join(sorted(dico.keys(), reverse=True))), lambda x: dico[x.group(1)], teststr)
Upvotes: 2
Reputation: 19144
Use a dict to get the substitution.
import re
d = {'aa': 'alpha', 'bb': 'beta', 'cc': 'gamma'}
teststr = 'A for <<aa>>, b means <<bb>>, and c could be <<cc>>.'
matches = re.finditer('<<(\w*)>>', teststr)
for i in matches:
teststr = teststr.replace(i.group(0), d[i.group(1)])
print(teststr)
prints A for alpha, b means beta, and c could be gamma.
Upvotes: 1