如何在不渲染的情况下合并非YAML格式的Go模板?
解决模板合并问题
方法1:Python脚本实现精准格式保留合并
由于你的模板是类YAML结构但包含Go模板变量,无法直接用标准YAML工具解析,我们可以通过提取键值对的方式,让v2的字段覆盖v1同名字段,同时完全保留原格式。
脚本示例:
def merge_templates(v1_path, v2_path, output_path): # 读取v1模板,构建键-原始行的映射,同时保留注释/空行 v1_map = {} v1_raw_lines = [] with open(v1_path, 'r') as f: for line in f: stripped_line = line.strip() # 保留注释和空行 if stripped_line.startswith('#') or not stripped_line: v1_raw_lines.append(line) continue # 提取键(仅分割第一个冒号) if ':' in line: key, _ = line.split(':', 1) key = key.strip() v1_map[key] = line v1_raw_lines.append(line) # 读取v2模板,更新映射中的覆盖项 with open(v2_path, 'r') as f: for line in f: stripped_line = line.strip() if stripped_line.startswith('#') or not stripped_line: continue if ':' in line: key, _ = line.split(':', 1) key = key.strip() v1_map[key] = line # 生成合并后的内容:替换被覆盖的行,保留其他原始内容 merged_content = [] for line in v1_raw_lines: stripped_line = line.strip() if stripped_line.startswith('#') or not stripped_line: merged_content.append(line) continue if ':' in line: key, _ = line.split(':', 1) key = key.strip() merged_content.append(v1_map[key]) else: merged_content.append(line) # 写入结果文件 with open(output_path, 'w') as f: f.writelines(merged_content) # 使用示例 merge_templates('v1.template', 'v2.template', 'merged.template')
该脚本特性:
- 完全保留原模板的注释、空行、缩进格式
- 用v2的键值对精准替换v1中同名字段
- 不修改Go模板变量
{{ ... }}的原始格式
方法2:Go模板原生组合实现覆盖
如果你的模板用于Go模板渲染场景,可以利用Go模板的define和block指令实现字段覆盖:
步骤1:定义基础模板(v1)
{{define "base"}} {{block "db_address"}}instance_db_address: {{ .MYSQL_ADDRESS }}{{end}} {{block "db_port"}}instance_db_port: {{ .MYSQL_PORT }}{{end}} imagePullSecrets: {{ .IMAGE_PULL_SECRET }} resources: requests: memory: "1Gi" cpu: "512m" limits: memory: "1Gi" cpu: "1000m" {{end}}
步骤2:定义覆盖模板(v2)
{{define "db_address"}}instance_db_address: {{ .MYSQL_ADDRESS2 }}{{end}} {{define "db_port"}}instance_db_port: {{ .MYSQL_PORT2 }}{{end}}
步骤3:渲染合并
同时解析两个模板后,执行{{template "base"}},v2的define会自动覆盖base中对应的block,输出你需要的合并结果。
方法3:awk命令快速合并(Linux/macOS场景)
在终端中可以用awk命令快速完成合并,无需编写复杂脚本:
awk ' BEGIN { # 先加载v2的键值对到数组 while ((getline line < "v2.template") > 0) { if (line ~ /^#/ || line ~ /^$/) continue split(line, arr, /:/) key = arr[1] gsub(/^[ \t]+|[ \t]+$/, "", key) v2[key] = line } close("v2.template") } # 处理v1的每一行 { if ($0 ~ /^#/ || $0 ~ /^$/) { print $0 next } split($0, arr, /:/) key = arr[1] gsub(/^[ \t]+|[ \t]+$/, "", key) print (v2[key] != "") ? v2[key] : $0 } ' v1.template > merged.template
该命令会跳过注释和空行,用v2的行替换v1中同名键的行,完全保留原始格式。
内容的提问来源于stack exchange,提问作者clarenceLiu
相关产品推荐
相关产品推荐

