Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用自定义双大括号格式的Python模板安全替换_Python_Regex_Templates_String Interpolation - Fatal编程技术网

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

使用自定义双大括号格式的Python模板安全替换,python,regex,templates,string-interpolation,Python,Regex,Templates,String Interpolation,我试图用Python的模板替换{{var}}格式的变量 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]*

我试图用Python的模板替换
{{var}}
格式的变量

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)
如您所见,
{{foo}
变量(它不是替换的一部分)的右括号被切掉了。我认为这是正则表达式的编写方式(结束语
\}


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

我不确定你是如何做到这一点的。在linux上,在Python3.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}}是不变的

我尝试了上面的代码,看起来该代码实际上不适用于Python2.7.6。我将看看是否能找到一种方法使其与2.7.6兼容,因为这似乎是最新linux发行版的常见版本

更新:

看起来这是2007年的一个已知错误。据我所知,它在2010年和2014年分别应用于Python3.2和Python2.7。为了让它发挥作用,您可以为问题1686应用修补程序,也可以使用此修补程序中的实际源代码覆盖类中的safe_substitute()

此代码适用于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)
问题
  • 开发人员reggie希望在python PEP292模板字符串中使用自定义占位符分隔符
解决方案(解决方案)
  • 开发者reggie可以更改占位符前缀字符
  • 这种方法允许使用完全不同的编程语言中的分隔符语法
  • 这种方法实现了更改占位符语法的主要目的,以防止分隔符冲突问题
  • 这种方法提供了子类化string.Template的最直接的例子
陷阱
  • 这种方法不支持像
    {{var}}
    这样的双大括号占位符
  • 在开发人员不能随意更改模板语法的情况下,这种方法没有帮助
例子 导入字符串 通过 类TemplateRubyish(string.Template): 分隔符='#' idpattern=r'[a-z][\w\,\+\=\:\-\.\x2f\x5c\*\(\)\[\]\x7c]*' 类TemplatePerlish(string.Template): 分隔符='qq' idpattern=r'[a-z][\w\,\+\=\:\-\.\x2f\x5c\*\(\)\[\]\x7c]*' 替换_dict={} 替换目录更新({ “年龄”:“34岁”, “fname”:“荷马”, “lname”:“辛普森”, }); 通过 ## vout=TemplateRubyish(“”)\ 问候{fname}{lname}, 你的年龄有点大了。 “”。安全替换(替换命令); 打印(vout) 通过 ## vout=TemplatePerlish(“”)\ 问候qq{fname}qq{lname}, 你已经有qq{age}岁了。 “”。安全替换(替换命令); 打印(vout) 通过 结果 你好,荷马·辛普森, 你已经34岁了。 你好,荷马·辛普森, 你已经34岁了。
您必须发布完整的正则表达式以及命名组与替换的关系。您可以尝试删除
转义的
无效的
组。它看起来像是
{{foo}}
匹配
{{
并且无效(它是空的)。因此,无论它在匹配时做什么都可能是问题。模板库的文档说需要提供四个命名组。这很奇怪。我的结果与你的不同。我已经发布了上面的完整示例。你能重新访问吗?
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)
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"
}
>>> 
import string pass class TemplateRubyish(string.Template): delimiter = '#' idpattern = r'[a-z][\w\,\+\=\:\-\.\x2f\x5c\*\(\)\[\]\x7c]*' class TemplatePerlish(string.Template): delimiter = 'qq' idpattern = r'[a-z][\w\,\+\=\:\-\.\x2f\x5c\*\(\)\[\]\x7c]*' replacement_dict = {} replacement_dict.update({ "age": "34", "fname": "Homer", "lname": "Simpson", }); pass ## vout = TemplateRubyish("""\ Greetings #{fname} #{lname}, You are #{age}ish years old. """).safe_substitute(replacement_dict); print(vout) pass ## vout = TemplatePerlish("""\ Greetings qq{fname} qq{lname}, You are qq{age}ish years old. """).safe_substitute(replacement_dict); print(vout) pass Greetings Homer Simpson, You are 34ish years old. Greetings Homer Simpson, You are 34ish years old.