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

Shell指定行号搜索替换异常:所有设备配置被批量修改

问题排查:VPP启动配置文件批量修改错误问题

配置文件初始格式

dev 1 {
    #num-tx-queues 64
    #num-rx-queues 64
}

dev 2 {
    #num-tx-queues 64
    #num-rx-queues 64
}
......

dev 8 {
     #num-tx-queues 64
     #num-rx-queues 64
}

注:文件包含完整8个设备配置,省略号仅为排版简化,所有配置项默认处于注释状态。

问题现象

需要解析环境变量,仅修改指定dev块的配置值,但使用sed按行号替换后,所有dev块的对应配置都被修改为目标值,不符合预期:

dev 1 {
        num-tx-queues 72
        num-rx-queues 72
}

dev 2 {
        num-tx-queues 72
        num-rx-queues 72
}
......

dev 8 {
        num-tx-queues 72
        num-rx-queues 72
} 

相关代码片段

function vpp_startup_file_update()
{
    i=$1;shift
    echo "Inside vpp_startup_file_update"
    for param in $@
    do
       name=${param%%=*}
       value=${param#*=}
       case $name in
            num-rx-queues)
                local line=$((i+2))
                sed -i "$line, \$s/^        #${name} [0-9]*/        ${name} ${value}/" "$CONF_FILE_PATH"
            ;;
            num-tx-queues)
                local line=$((i+1))
                sed -i "$line, \$s/^        #${name} [0-9]*/        ${name} ${value}/" "$CONF_FILE_PATH"
            ;;
            num-tx-desc)
                local line=$((i+3))
                sed -i "$line, \$s/^        #${name} [0-9]*/        ${name} ${value}/" "$CONF_FILE_PATH"
            ;;
            num-rx-desc)
                local line=$((i+4))
                sed -i "$line, \$s/^        #${name} [0-9]*/        ${name} ${value}/" "$CONF_FILE_PATH"
            ;;
            *)
                echo "Parameter : $name value : $value does not match any case"
            ;;
       esac

    done
}

vpp_dpdk_dev_conf="dev=name=a,pci=2,mtu=1400,num-rx-queues=72,num-tx-queues=72,num-rx-desc=8,num-tx-desc=8,skip=false|true"
IFS=','

declare -a DEV=($vpp_dpdk_dev_conf)
for i in ${DEV[@]}; do
    for param in $(IFS='=';echo $i); do
        name=${param%% *}
        value=${param#* }
        cout=1
        case $name in
            pci)
                line_num=$(grep -Fn "dev $value" $CONF_FILE_PATH | cut --delimiter=":" --fields=1)
                vpp_startup_file_update $line_num "${DEV[@]}"
                break
            ;;

问题根源

  1. sed范围匹配错误:当前sed命令使用$line, \$作为匹配范围,意思是从目标行开始到文件末尾,所有符合正则的行都会被替换,直接导致后续所有dev块的同名称配置项被批量修改。
  2. 参数传递逻辑错误:调用vpp_startup_file_update时传入了${DEV[@]},会把所有dev的参数都传递进去,造成重复处理。
  3. 行号偏移不可靠:依赖固定行号偏移计算配置项位置,一旦配置文件格式变化(如空行、注释调整),偏移就会失效,鲁棒性极差。

优化解决方案

核心修复:限定sed仅修改目标dev块

利用sed的地址范围匹配,锁定目标dev块的起始(dev X {)和结束(})位置,只在该范围内执行替换:

# 以num-tx-queues为例,替换原sed命令
sed -i "/^dev $dev_num {/,/^}/s/^[[:space:]]*#${name} [0-9]*/        ${name} ${value}/" "$CONF_FILE_PATH"

重构后的完整代码

function vpp_startup_file_update() {
    local dev_num=$1
    shift
    local conf_file="$CONF_FILE_PATH"
    
    for param in "$@"; do
        local name=${param%%=*}
        local value=${param#*=}
        
        case "$name" in
            num-rx-queues|num-tx-queues|num-tx-desc|num-rx-desc)
                # 仅在目标dev块内替换配置
                sed -i "/^dev $dev_num {/,/^}/s/^[[:space:]]*#${name} [0-9]*/        ${name} ${value}/" "$conf_file"
                ;;
            *)
                echo "未知参数: $name = $value"
                ;;
        esac
    done
}

# 解析环境变量,按|分割多个dev配置
vpp_dpdk_dev_conf="dev=name=a,pci=2,mtu=1400,num-rx-queues=72,num-tx-queues=72,num-rx-desc=8,num-tx-desc=8,skip=false|dev=name=b,pci=3,num-rx-queues=64,num-tx-queues=64"
CONF_FILE_PATH="/path/to/your/vpp/startup.conf"

IFS='|' read -ra DEV_LIST <<< "$vpp_dpdk_dev_conf"

for dev_conf in "${DEV_LIST[@]}"; do
    local dev_num=""
    local params=()
    IFS=',' read -ra DEV_PARAMS <<< "$dev_conf"
    
    for param in "${DEV_PARAMS[@]}"; do
        local name=${param%%=*}
        local value=${param#*=}
        
        if [[ "$name" == "pci" ]]; then
            dev_num="$value"
        else
            params+=("$param")
        fi
    done
    
    if [[ -n "$dev_num" ]]; then
        vpp_startup_file_update "$dev_num" "${params[@]}"
    fi
done

额外优化建议

  • 使用[[:space:]]*匹配任意空白字符,避免依赖固定空格数量,适配不同格式的配置文件。
  • 用read -ra解析环境变量,替代直接赋值数组,避免空格等特殊字符导致的拆分错误。
  • 增加dev编号校验,先检查配置文件中是否存在目标dev块,再执行修改,避免无效操作。

内容的提问来源于stack exchange,提问作者Niladri Chakraborty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:13:13