You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 11:06:02