How to replace the variable value in the variable $ template

demand

We frequently need to pre-defined data template is embedded placeholder variables, such as $ name or {{name}} or% (name) s, to facilitate replacement of parameters do.
This requires the use of string format or template engine (such as Jinja2) you will be ready to replace a group of data into the template to the location specified.
Python comes with string formatting there are three general ways:

  1. The% s or% (name) s
'姓名: %s, 年龄: %d' %('Kevin', 21) 
'姓名: %(name)s, 年龄: %(age)d' % {'name':'Kevin', 'age': 21} 
  1. Use .format syntax
'姓名: {}, 年龄: {}'.format('Kevin', 21) 
'姓名: {name}, 年龄: {age}'.format(name='Kevin', age=21) 
  1. Use Template and safe_substitute ()
from string import Template
Template('姓名: $name, 年龄: $age').safe_substitute(name='Kevin', age=21)

Specific template rendering engine, such as Jinja2, in addition to rendering the variable supports more features, such as determining if and for loop iterates, filters and the like, using a simple method as follows:

from jinja2 import Template
Template('姓名: {{ name }}, 年龄: {{age}}').render(name='Kevin', age=21)

Yaml file types for rendering embedded variables, or use {%} will be some problems, so we choose to use the $ here as delimiters, sometimes we need to variable substitution in the de-serialization and then, and for a list / dictionary species Alternatively embedded variable, e.g., there is such a list:

 s = ['性别: $2  年龄: $3\n$a', '$1', {"say": "$a"}]

We need to replace the data in, which $1represents the first argument, $athe representative parameters a
then use the safe_subtitute()method more trouble, so here is simple implements a
$ variable substitution method

characteristic

  1. Support $1to replace the first parameter, and $areplace parametersa
  2. Replace support dictionary / list / Ganso, and nested dictionary / variable list
  3. It supports the specified delimiter defaults$
  4. It supports multi-line text replacement
  5. When not completely replace, retain the original value, not being given

The principle

Python regular sub Method re library support for custom handlers replacement

re.sub(匹配表达式, 替换值或替换处理函数, 原始文本, re.M)   # 使用re.M 支持跨行

Implementation code

import re
import json

def render(origin, *args, delimiter="$", **kwargs):  # 支持修改delimiter定界符
    patten = r'\{}(?P<var>[\w|_]+)'.format(delimiter)

    def repl_func(matched):   # 自定义re.sub使用的替换方法
        var = matched.group('var')
        if var.isdigit():   # 如果是数字, 则从args中替换
            index = int(var) - 1
            if index < len(args):
                return args[index]
            else:
                return "{}{}".format(delimiter, var)   # 无替换参数则返回原值
        else:
            return kwargs.get(var, None) or "{}{}".format(delimiter, var)   # 返回kwargs参数中值 or 原值

    if isinstance(origin, str):
        return re.sub(patten, repl_func, origin, re.M)
    elif isinstance(origin, (dict, list)):  # 使用json.dumps转为字符串, 替换,然后重新转为dict/list
        return json.loads(re.sub(patten, repl_func, json.dumps(origin), re.M))
    else:
        if isinstance(origin, tuple):
            return tuple(json.loads(re.sub(patten, repl_func, json.dumps(origin), re.M)))  # 转换后重新转为tuple


if __name__ == '__main__':
    s = ['性别: $2  年龄: $3\n$a', '$1', {"say": "$a"}]
    print(render(s, 'kevin', 'male', '20', a="hello, world!"))

Output:


['性别: male  年龄: 20\nhello, world!', 'kevin', {'say': 'hello, world!'}]

Guess you like

Origin www.cnblogs.com/superhin/p/11454931.html