使用sed命令修改YAML文件含下划线键值失败求助
问题:sed修改YAML中app2的value_3值无效的原因及解决办法
原始YAML内容(test.yaml)
app1: value1: 0 value2: 7 value_3: 5 app2: value1: 1 value2: 6 value_3: 0
现象
- 执行以下命令可成功将app2的value2值改为0:
sed -i '/app2/ {n;N;s/value2: 6/value2: 0/}' test.yaml - 但执行类似命令修改app2的value_3值时,无报错但值未变化:
sed -i '/app2/ {n;N;s/value_3: 0/value_3: 6/}' test.yaml
原因
这不是sed的bug,是操作逻辑有误。/app2/ {n;N;...}的执行流程是:
- 匹配到
app2:所在行后,n命令读取下一行(即value1: 1)并替换当前模式空间内容; - 接着
N命令再读取下一行(即value2: 6)追加到模式空间,此时模式空间里只有这两行内容; - 后续的
s命令只能在这两行里匹配替换,而value_3: 0是app2下的第三行,根本没被读到模式空间中,所以替换无效。
解决办法
方法1:使用地址范围匹配
通过指定从app2:到下一个app节点的范围,在这个范围内替换目标值:
sed -i '/app2:/,/^ [a-z0-9]*:/ s/value_3: 0/value_3: 6/' test.yaml
/app2:/:匹配app2节点的起始行/^ [a-z0-9]*:/:匹配下一个以两个空格开头的app节点行(适配YAML的缩进格式)- 中间的
s命令会在这个范围内所有行中执行替换
方法2:循环读取直到找到目标行
用sed的标签循环,读取app2之后的行直到找到value_3:并替换,可选添加退出条件避免影响后续内容:
# 无退出条件(适用于app2是最后一个节点的情况) sed -i '/app2:/ { :loop; n; /value_3:/ s/0/6/; b loop }' test.yaml # 带退出条件(读到下一个app节点就停止,更安全) sed -i '/app2:/ { :loop; n; /^ [a-z0-9]*:/q; /value_3:/ s/0/6/; b loop }' test.yaml
:loop:定义循环标签n:读取下一行/^ [a-z0-9]*:/q:匹配到下一个app节点时退出(q命令结束sed进程)/value_3:/ s/0/6/:匹配到目标行时执行替换b loop:跳回loop标签继续循环
内容的提问来源于stack exchange,提问作者theghoul
相关产品推荐
相关产品推荐

