これは、小さなバグを持っている@ ShawnFumoの答えに若干の変更があります。失敗したキーと同じ文字列で始まる別のキーだけが一致するように、単語境界チェック(正規表現では\ b)を追加する必要があります。これにより、{foo}キーが{food}と{foolish}が欠けているかのように扱われるのを防ぐことができます。
import re
def my_format(template, *args, **kwargs):
next_index = len(args)
while True:
try:
return template.format(*args, **kwargs)
except KeyError as e:
key = e.args[0]
finder = r'\{' + key + r'\b.*?\}'
template = re.sub(finder, r'{\g<0>}', template)
except IndexError as e:
args = args + ('{' + str(next_index) + '}',)
next_index += 1
だから、それをテストするには:
class MyObj:
bar = 'baz'
def __repr__(self):
return '<MyObj instance>'
my_obj = MyObj()
template = '{0}, {1}, {foo}, {foo.bar}, {0}, {10}, {missing}'
print my_format(template)
print my_format(template, '1st', '2nd', missing='Not Missing')
print my_format(template, foo=my_obj)
print
template2 = '{foo} and {food}'
print my_format(template2)
print my_format(template2, food='burger')
print my_format(template2, foo=my_obj, food='burger')
出力:
class LazyFormatter(string.Formatter):
def get_value(self, key, args, kwargs):
'''Overrides string.Formatter.get_value'''
if isinstance(key, (int, long)):
return args[key]
else:
return kwargs.get(key, '{{{0}}}'.format(key))
lazyfmt = LazyFormatter()
print lazyfmt.format("{field}: {value}", **{'field': 'foo'})
出力:012 string.Template.safe_substitute
に代わるものはそうのようstring.Formatter
をサブクラス化することができ
{0}, {1}, {foo}, {foo.bar}, {0}, {10}, {missing}
1st, 2nd, {foo}, {foo.bar}, 1st, {10}, Not Missing
{0}, {1}, <MyObj instance>, baz, {0}, {10}, {missing}
{foo} and {food}
{foo} and burger
repr(<MyObj instance>) and burger
もちろん、SQLインジェクション攻撃を防ぐために、置換文字列をすべてエスケープしようとしているのでしょうか? ;) –
あなたの* * *ユーザーの入力がこれに入ることを*これまでには望んでいないのですか?この種のコードは、セキュリティホールを要求しています。 –
もちろん、私はそれをやることはしません。おそらくそれは最良の例ではありませんでしたが、最初に私の心に来たものでした。 – santiagobasulto