Shell脚本更新模板中network与subnet ID的问题求助
解决Shell脚本批量更新YAML模板中Network/Subnet的问题
问题
我想用Shell脚本将指定的network和subnet ID更新到YAML模板文件中,但使用sed命令替换时,所有network/subnet行都被更新为相同值,求正确实现方法。
待更新的值
net1="network1" sub1="subnet1" net2="network2" sub2="subnet2" net3="network3" sub3="subnet3" net4="network4" sub4="subnet4"
模板文件内容
vm_group: - name: man1 image: ubuntu18.04 flavor: ram12 volume: 500 ext_net: - network: subnet: - network: subnet: - network: subnet: - network: subnet: sriov:enabled zone: availablity-zone1 vm_group: - name: man2 image: ubuntu18.04 flavor: ram12 volume: 500 ext_net: - network: subnet: - network: subnet: - network: subnet: - network: subnet: sriov:enabled zone: availablity-zone2
已尝试的脚本
file_path="path/to/your/file.yaml" # Replace network and subnet values for man1 group sed -i "s/\(network:\).*/\1 ${net1}\n subnet: ${sub1}\n - network: ${net2}\n subnet: ${sub2}\n - network: ${net3}\n subnet: ${sub3}\n - network: ${net4}\n subnet: ${sub4}/" ${file_path} # Replace network and subnet values for man2 group sed -i "s/\(network:\).*/\1 ${net1}\n subnet: ${sub1}\n - network: ${net3}\n subnet: ${sub3}\n - network: ${net4}\n subnet: ${sub4}\n - network: ${net2}\n subnet: ${sub2}/" ${file_path}
期望输出
vm_group: - name: man1 image: ubuntu18.04 flavor: ram12 volume: 500 ext_net: - network: net1 subnet: sub1 - network: net2 subnet: sub2 - network: net3 subnet: sub3 - network: net4 subnet: sub4 sriov:enabled zone: availablity-zone1 vm_group: - name: man2 image: ubuntu18.04 flavor: ram12 volume: 500 ext_net: - network: net3 subnet: sub3 - network: net1 subnet: sub1 - network: net4 subnet: sub4 - network: net2 subnet: sub2 sriov:enabled zone: availablity-zone2
解决方案
问题原因
原sed命令的s/\(network:\).*/.../会匹配文件中所有network:行,每次执行都会替换所有匹配内容,导致两次替换互相覆盖,最终所有network/subnet行都变成同一组值。需要精准定位每个vm_group下的ext_net条目,只替换目标块内的内容。
方法1:使用awk处理(推荐,更稳定)
awk可以跟踪当前所在的vm_group和ext_net条目计数,精准替换对应位置的值:
# 定义变量 net1="network1" sub1="subnet1" net2="network2" sub2="subnet2" net3="network3" sub3="subnet3" net4="network4" sub4="subnet4" file_path="path/to/your/file.yaml" # 执行awk替换 awk -v net1="$net1" -v sub1="$sub1" \ -v net2="$net2" -v sub2="$sub2" \ -v net3="$net3" -v sub3="$sub3" \ -v net4="$net4" -v sub4="$sub4" ' # 标记进入man1的块 /^ - name: man1$/ { in_man1=1; in_man2=0; count=0 } # 标记离开man1的块 /^ zone: availablity-zone1$/ { in_man1=0 } # 标记进入man2的块 /^ - name: man2$/ { in_man2=1; in_man1=0; count=0 } # 标记离开man2的块 /^ zone: availablity-zone2$/ { in_man2=0 } # 处理man1的network行 in_man1 && /^ - network:/ { count++ if (count == 1) { print " - network: " net1 } else if (count == 2) { print " - network: " net2 } else if (count == 3) { print " - network: " net3 } else if (count == 4) { print " - network: " net4 } next } # 处理man1的subnet行 in_man1 && /^ subnet:/ { if (count == 1) { print " subnet: " sub1 } else if (count == 2) { print " subnet: " sub2 } else if (count == 3) { print " subnet: " sub3 } else if (count == 4) { print " subnet: " sub4 } next } # 处理man2的network行(按期望顺序) in_man2 && /^ - network:/ { count++ if (count == 1) { print " - network: " net3 } else if (count == 2) { print " - network: " net1 } else if (count == 3) { print " - network: " net4 } else if (count == 4) { print " - network: " net2 } next } # 处理man2的subnet行(按期望顺序) in_man2 && /^ subnet:/ { if (count == 1) { print " subnet: " sub3 } else if (count == 2) { print " subnet: " sub1 } else if (count == 3) { print " subnet: " sub4 } else if (count == 4) { print " subnet: " sub2 } next } # 其他行直接输出 { print } ' "${file_path}" > temp.yaml && mv temp.yaml "${file_path}"
方法2:使用sed的地址范围匹配
利用sed的地址范围限定替换仅在目标vm_group块内执行,结合计数匹配指定条目:
# 定义变量 net1="network1" sub1="subnet1" net2="network2" sub2="subnet2" net3="network3" sub3="subnet3" net4="network4" sub4="subnet4" file_path="path/to/your/file.yaml" # 替换man1的ext_net条目 sed -i '/- name: man1/,/zone: availablity-zone1/ { # 第1组network/subnet 0,/network:/ s/\(network:\).*/\1 '"${net1}"'/ 0,/subnet:/ s/\(subnet:\).*/\1 '"${sub1}"'/ # 第2组network/subnet /network:/,/subnet:/! { /network:/ s/\(network:\).*/\1 '"${net2}"'/ } /subnet:/,/network:/! { /subnet:/ s/\(subnet:\).*/\1 '"${sub2}"'/ } # 第3组network/subnet /network:/{3} s/\(network:\).*/\1 '"${net3}"'/ /subnet:/{3} s/\(subnet:\).*/\1 '"${sub3}"'/ # 第4组network/subnet /network:/{4} s/\(network:\).*/\1 '"${net4}"'/ /subnet:/{4} s/\(subnet:\).*/\1 '"${sub4}"'/ }' "${file_path}" # 替换man2的ext_net条目(按期望顺序) sed -i '/- name: man2/,/zone: availablity-zone2/ { # 第1组network/subnet 0,/network:/ s/\(network:\).*/\1 '"${net3}"'/ 0,/subnet:/ s/\(subnet:\).*/\1 '"${sub3}"'/ # 第2组network/subnet /network:/,/subnet:/! { /network:/ s/\(network:\).*/\1 '"${net1}"'/ } /subnet:/,/network:/! { /subnet:/ s/\(subnet:\).*/\1 '"${sub1}"'/ } # 第3组network/subnet /network:/{3} s/\(network:\).*/\1 '"${net4}"'/ /subnet:/{3} s/\(subnet:\).*/\1 '"${sub4}"'/ # 第4组network/subnet /network:/{4} s/\(network:\).*/\1 '"${net2}"'/ /subnet:/{4} s/\(subnet:\).*/\1 '"${sub2}"'/ }' "${file_path}"
内容的提问来源于stack exchange,提问作者Beginner
相关产品推荐
相关产品推荐

