使用自定义双括号格式进行 Python 模板安全替换

2023-12-29

我正在尝试替换格式中的变量{{var}}与Python的模板。

from string import Template

class CustomTemplate(Template):
    delimiter = '{{'
    pattern = r'''
    \{\{(?:
    (?P<escaped>\{\{)|
    (?P<named>[_a-z][_a-z0-9]*)\}\}|
    (?P<braced>[_a-z][_a-z0-9]*)\}\}|
    (?P<invalid>)
    )
    '''

replacement_dict = {
    "test": "hello"
}

tpl = '''{
    "unaltered": "{{foo}}",
    "replaced": "{{test}}"
}'''

a = CustomTemplate(tpl)
b = a.safe_substitute(replacement_dict)

print(b)

输出:

{
    "unaltered": "{{foo",
    "replaced": "hello"
}

如您所见,{{foo}}变量(不是替换的一部分)的右括号被砍掉。我认为这是正则表达式的编写方式(结束语\}\})?

我想用模板解决这个问题,而不是用任何其他外部库。


我不确定你是如何让它发挥作用的。在linux上,在python 3.4.3中(我想我可以在2.7的某些版本上使用它)我需要使 tpl 成为一个字符串

tpl = '''
    "unaltered": "{{foo}}",
    "replaced": "{{test}}"
'''

以避免出现类型错误

>>> tpl = '''
...     "unaltered": "{{foo}}",
...     "replaced": "{{test}}"
... '''
>>> a = CustomTemplate(tpl)
>>> a.template
'\n    "unaltered": "{{foo}}",\n    "replaced": "{{test}}"\n'
>>> b = a.safe_substitute(replacement_dict)
>>> b
'\n    "unaltered": "{{foo}}",\n    "replaced": "hello"\n'

当我这样做时,{{foo}} 没有改变。

我尝试了上面的代码,看起来该代码实际上不适用于 python 2.7.6。我会看看是否能找到一种方法让它与 2.7.6 一起工作,因为这似乎是最近 Linux 发行版的常见版本。

update:

看起来这是 2007 年的一个已知错误。http://bugs.python.org/issue1686 http://bugs.python.org/issue1686据我所知,它于 2010 年应用于 python 3.2,并于 2014 年应用于 python 2.7。要使其发挥作用,您可以应用问题 1686 的补丁,也可以在类中使用以下命令覆盖 safe_substitute()该补丁的实际源代码https://hg.python.org/cpython/file/8a98ee6baa1e/Lib/string.py https://hg.python.org/cpython/file/8a98ee6baa1e/Lib/string.py.

此代码适用于 2.7.6 和 3.4.3

from string import Template
class CustomTemplate(Template):
    delimiter = '{{'
    pattern = r'''
    \{\{(?:
    (?P<escaped>\{\{)|
    (?P<named>[_a-z][_a-z0-9]*)\}\}|
    (?P<braced>[_a-z][_a-z0-9]*)\}\}|
    (?P<invalid>)
    )
    '''

    def safe_substitute(self, *args, **kws):
        if len(args) > 1:
            raise TypeError('Too many positional arguments')
        if not args:
            mapping = kws
        elif kws:
            mapping = _multimap(kws, args[0])
        else:
            mapping = args[0]
        # Helper function for .sub()
        def convert(mo):
            named = mo.group('named') or mo.group('braced')
            if named is not None:
                try:
                    # We use this idiom instead of str() because the latter
                    # will fail if val is a Unicode containing non-ASCII
                    return '%s' % (mapping[named],)
                except KeyError:
                    return mo.group()
            if mo.group('escaped') is not None:
                return self.delimiter
            if mo.group('invalid') is not None:
                return mo.group()
            raise ValueError('Unrecognized named group in pattern',
                             self.pattern)
        return self.pattern.sub(convert, self.template)

replacement_dict = {
    "test": "hello"
}

tpl = '''{
    "escaped": "{{{{",
    "unaltered": "{{foo}}",
    "replaced": "{{test}}",
    "invalid": "{{az"
}'''

a = CustomTemplate(tpl)
b = a.safe_substitute(replacement_dict)

print (b)

results:

Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import template
{
    "escaped": "{{",
    "unaltered": "{{foo}}",
    "replaced": "hello",
    "invalid": "{{az"
}
>>> 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用自定义双括号格式进行 Python 模板安全替换 的相关文章

随机推荐