如何用bash结合awk修改YAML文件,向monitor_vms段批量添加VM条目
实现方案
现有代码的核心问题
- 入参接收错误:getline函数没有正确接收传入的YAML路径和目标键名,awk内部的
monitor_vms变量赋值语法错误 - 匹配规则错误:原YAML中
monitor_vms前带有-前缀,原有正则^monitor_vms:无法命中 - 变量引用错误:循环中定义的变量是
name,实际插入时引用了不存在的vmname变量 - 逻辑效率问题:每次插入前都重新计算行号,插入后行号偏移会导致后续插入位置错误,且多次调用sed修改文件效率极低
- sed语法错误:命令未闭合,插入内容缺少YAML要求的缩进,格式不符合规范
修正后的完整脚本
#!/bin/bash # 入参校验:至少需要1个yaml文件参数 + 1个VM参数 if [ $# -lt 2 ]; then echo "用法: $0 <yaml文件路径> <VM名1> [VM名2] ..." exit 1 fi YAML_FILE="$1" shift # 移除第一个参数,剩下的都是VM列表 VM_LIST=("$@") # 定位monitor_vms配置段的末尾行号 get_insert_line() { awk ' BEGIN { fnd = 0 last_line = 1 } # 匹配到monitor_vms段开始 /^- monitor_vms:/ { fnd = 1 } # 已经进入monitor_vms段,匹配到下一个同级的键(开头是"- ")说明段结束 fnd == 1 && /^- / && !/^- monitor_vms:/ { exit } # 记录monitor_vms段内的最后一个非空非注释行号 fnd == 1 && $0 ~ /./ && $0 !~ /^[[:space:]]*#/ { last_line = NR } END { print last_line }' "$YAML_FILE" } # 先计算一次插入位置 insert_line=$(get_insert_line) # 拼接所有要插入的VM条目,统一用2个空格缩进符合YAML格式 insert_content="" for vm in "${VM_LIST[@]}"; do insert_content="${insert_content} - name: ${vm}"$'\n' done # 一次性插入所有内容,兼容GNU/BSD sed sed -i.bak "${insert_line}a\\ ${insert_content}" "$YAML_FILE" # 可选:删除sed自动生成的备份文件 rm -f "${YAML_FILE}.bak" echo "已成功将${#VM_LIST[@]}个VM添加到${YAML_FILE}的monitor_vms段"
使用方法
和要求的调用方式完全一致:
myscript.sh my.yaml neo1 neo2 neo3 alice1 alice2 alice3
执行后会直接修改目标YAML文件,生成的内容完全符合期望格式,YAML缩进正确,不会破坏原有配置结构。
内容的提问来源于stack exchange,提问作者Neo Vijay
相关产品推荐
相关产品推荐

