1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
| from typing import Dict, List, Tuple
def _search(string: str) -> Tuple[str, Tuple[int, int]]: """单次搜索模板串
Args: string: 目标字符串
Return: 模板串, 以及在原始字符串中的起止坐标 当字符串里不存在插值模板时返回空值. 例 -> ('', (None, None)) """ i = 0 s_list = list(string) s_len = len(s_list) _stack = [] _temp = [] _start = None _end = None
while i < s_len: if _start is not None and _end is not None: break
if len(_stack) >= 2: _temp.append(s_list[i])
if s_list[i] == "{": try: _next = s_list[i + 1] except IndexError: raise SyntaxError("格式不正确, 缺少 {") if _next == "{": _stack.append(s_list[i]) _stack.append(s_list[i + 1]) _temp.append(s_list[i]) _temp.append(s_list[i + 1]) _start = i i += 2 continue else: _stack.append(s_list[i])
if s_list[i] == "}": if len(_stack) == 2: try: _next = s_list[i + 1] except IndexError: raise SyntaxError("格式不正确, 缺少 }") if _next != "}": raise SyntaxError("格式不正确, 缺少 }") _stack.clear() i += 2 _temp.append(_next) _end = i continue
if _stack: _stack.pop()
i += 1
if _stack: raise SyntaxError("格式不正确, 缺少 }")
return ("".join(_temp), (_start, _end))
def _var_name(temp_string: str) -> str: try: var = temp_string[2:-2] except IndexError: raise SyntaxError("格式不正确") return var.strip()
def _replace(string: str, k1: str, k2: str) -> str: """ Args:
string: 原始字符串 k1: 被替换的子串 k2: 替换后的子串
""" s_list = list(string) s_len = len(s_list)
k1, k2 = str(k1), str(k2) k1_list, k2_list = list(k1), list(k2) k1_len, k2_len = len(k1_list), len(k2_list)
res = list()
i = 0 _temp = 0 while i < s_len: if s_list[i] == k1_list[0]: for j in range(k1_len): if k1_list[j] == s_list[i + j]: _temp += 1 else: break
if _temp == k1_len: res.extend(k2_list) i += (k1_len - 1) else: res.append(s_list[i])
i += 1 _temp = 0
return "".join(res)
def render(string: str, values: Dict[str, Tuple[str, int]]) -> str: """渲染模板字符串
逻辑概要
string = "my {{ name }} is, {{ age }} !!" 查找到第一个模板串 "{{ name }}", 然后提取左串
l_string = "my {{ name }}"
将左串替换后的结果增加到 s_list, 然后更新 _temp 为右串
_temp = " is, {{ age }} !!" 直至搜索不到模板串, 替换完毕. """ s_list = list() _temp = string while True: t_string, (i_start, i_end) = _search(_temp) if i_start is None or i_end is None: break
name = _var_name(t_string) if name not in values: raise ValueError(f"缺少关键字 {name}") value = str(values[name])
l_string = _replace(_temp[: i_end], t_string, value) s_list.append(l_string) _temp = _temp[i_end:]
s_list.append(_temp) return "".join(s_list)
|