我是 Bash 新手,遇到了一个问题,我需要更新 yaml 文件中的某些动态参数
根据查询 ( search4.subsearch1.name
),我需要更新
name: old_name
进入
name: new_name
- 这是示例文件:
search1: name: name1 pass: pass1 date: date1 #these are just commented texts search2: #Adding few more commented lines myname: somename name: name2 pass: pass2 someotherparam: param1 search3: nameAndSurname: NS namingConv: true varSet: P3 search4: #Again adding some special name: strings here myname: somename1 name: new_name pass: new_pass ptherparam1: T3 subsearch1: #Again adding some special name strings here myname: somename2 name: old_name pass: pass2 ptherparam1: param3 search5: #Again adding some special name strings here var1: value1 name: some_name pass: some_pass
因此,根据查询(search4.subsearch1.name
),我需要更新name: old_name
为name: new_name
- 预期输出:
search4: #Again adding some special name: strings here myname: somename1 name: new_name pass: new_pass ptherparam1: T3 subsearch1: #Again adding some special name strings here myname: somename2 name: new_name pass: pass2 ptherparam1: param3
尝试使用awk
andsed
但没有成功:
lineNR=$(awk "/\<search4:/{f=1} f && /\<name:/ {print NR; exit}" testfile.txt);sed "${lineNR}s/name.*/name: new_name/" testfile.txt
答案1
答案2
您没有告诉我们您正在使用什么系统或已经安装了什么系统。所以这只是一个有根据的猜测。许多 Linux 发行版都附带“python”,而 yaml 的兴起意味着它也经常安装库“pyaml”。您自己与 yaml 文件交互这一事实使得这种情况更有可能发生。
您可以非常轻松地对此进行测试。创建一个仅包含以下内容的文件foo.py
:
import yaml
print("I have yaml")
然后在命令行运行:
python3 foo.py
如果它只是打印,I have yaml
那么您已经安装了 python 和 pyaml,并且可以在简单的脚本中使用它 ( update_script.py
):
import yaml
import sys
# Load the file into a data structure
with open(sys.argv[1], "r") as file:
content = yaml.safe_load(file)
# Update the key you want to change
content["search4"]["subsearch1"]["name"] = "new_name"
# Write the data structure back to your file in YAML
with open(sys.argv[1], "w") as file:
yaml.safe_dump(content, file)
然后运行:
python3 update_script.py config_file.yaml
答案3
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ cat tst.awk
NF && !/^[[:space:]]*#/ && match($0,/^[[:space:]]*/) {
prevIndent = currIndent
currIndent = RLENGTH
name = $1
sub(/:.*/,"",name)
if ( currIndent == 0 ) {
path = name
}
else {
if ( currIndent <= prevIndent ) {
sub(/\.[^.]+$/,"",path)
}
path = path "." name
}
if ( path == tgt ) {
$0 = substr($0,1,currIndent) $1 " " val
}
}
{ print }
$ awk -v tgt='search4.subsearch1.name' -v val='new_name' -f tst.awk file
search1:
name: name1
pass: pass1
date: date1
#these are just commented texts
search2:
#Adding few more commented lines
myname: somename
name: name2
pass: pass2
someotherparam: param1
search3:
nameAndSurname: NS
namingConv: true
varSet: P3
search4:
#Again adding some special name: strings here
myname: somename1
name: new_name
pass: new_pass
ptherparam1: T3
subsearch1:
#Again adding some special name strings here
myname: somename2
name: new_name
pass: pass2
ptherparam1: param3
search5:
#Again adding some special name strings here
var1: value1
name: some_name
pass: some_pass
上面不是 YAML 解析器,仅适用于与所示示例结构相同的文件,并且所有缩进都是制表符或空格,但不能同时是两者。
看https://stackoverflow.com/questions/66173552/update-yaml-value-on-cli#comment116993514_66173552对于上述的另一个应用。