如何用Awk实现Helm Values YAML文件的指定字符串替换?
问题描述
我在处理Helm Values的YAML文件,需要实现字符串搜索替换:
基础场景:
已通过命令diff a.yaml b.yaml|grep ">"|cut -c 3- > new_file.yaml提取两个文件的差异内容。- a.yaml内容:
NAME_VAR: {{ .Data.data.name_var }} SOME_VALUE: {{ .Data.data.some_value }} ONE_MORE: {{ .Data.data.one_more }} - b.yaml内容:
NAME_VAR: {{ .Data.data.name_var }} SOME_VALUE: {{ .Data.data.some_value }} ONE_MORE: {{ .Data.data.one_more }} ADD_THIS: {{ .Data.data.<change_me> }}
生成的new_file.yaml内容:
ADD_THIS: {{ .Data.data.<change_me> }}需要将该行中的
<change_me>替换为对应键名的小写形式(如ADD_THIS转为add_this),最终得到:ADD_THIS: {{ .Data.data.add_this }}- a.yaml内容:
补充场景:
当b.yaml存在多个需要补全的字段时,现有方案会出现重复行问题:- a.yaml内容不变,b.yaml内容:
NAME_VAR: {{ .Data.data.name_var }} SOME_VALUE: {{ .Data.data. }} ONE_MORE: {{ .Data.data. }} ADD_THIS: {{ .Data.data. }}
现有方案输出存在重复行:
ADD_THIS: {{ .Data.data.add_this }} SOME_VALUE: {{ .Data.data.some_value }} ONE_MORE: {{ .Data.data.one_more }} SOME_VALUE: {{ .Data.data.some_value }} ONE_MORE: {{ .Data.data.one_more }}- a.yaml内容不变,b.yaml内容:
解决方案
针对基础场景(处理已提取的new_file.yaml)
使用awk完成键名转小写并替换目标内容:
awk -F ': ' '{ key = $1 lower_key = tolower(key) sub(/<change_me>/, lower_key, $2) print $0 }' new_file.yaml
该命令会提取每行的键名,转为小写后替换<change_me>,输出符合要求的行。
针对补充场景(避免重复行,直接对比a/b文件完成处理)
跳过单独提取差异的步骤,直接用awk对比a.yaml和b.yaml,只处理b中与a不同的行,同时完成补全替换:
awk ' NR == FNR { # 读取a.yaml,存储键名对应的值 map[$1] = $2 next } # 只处理b中存在于a且值不同的行 $1 in map && $2 != map[$1] { key = $1 lower_key = tolower(key) # 同时处理两种情况:<change_me> 或 .data.结尾的空内容 sub(/<change_me>|(\.data\.)$/, "\\1"lower_key, $2) print $0 }' a.yaml b.yaml
这个命令会:
- 先加载a.yaml的键值对到数组
- 遍历b.yaml时,只处理值与a不一致的行
- 自动补全
{{ .Data.data. }}后的空缺,或替换<change_me>为小写键名 - 不会产生重复行,因为每个键仅处理一次
内容的提问来源于stack exchange,提问作者Andres Cabrera
相关产品推荐
相关产品推荐

