【发布时间】:2018-05-09 12:47:30
【问题描述】:
我对 BASH、JSON 和 jq 完全陌生(实习生不到两周的实践经验)。但是我被赋予了一项任务来迭代地替换数组中的 JSON 对象值。我已经设法编写了以下代码。
我正在尝试将 json 文件中的键“名称”的值增量替换为存储在另一个文本文件中的数组中的名称。基本上只是更新节点的名称。
这是要替换的 JSON 文件的 sn-p。整个文件太大了,不能在这里发布。 但是键“name”的路径是“.lab.racks[].nodes[].name”
"roles": [
"bla bla",
"bla bla"
],
"name": "Node1",
"power": {
"address": "10.182.149.145",
"type": "bla bla",
"user": "bla bla",
"pass": "bla bla "
},
“名称”:“Node1”必须替换为“名称”:“Tom-cat”。名称 Tom-cat 是动态生成的,并且每次运行金属即服务 (MaaS) 脚本时都会更改。这个名称“Tom-cat”和 MaaS 生成的所有其他新名称被剪切(使用 awk)并存储在文本文件 newhostnames.txt 中
文本文件看起来像这样
#newhostnames.txt
Tom-cat
Lucky-worm
Wom-bat
所以目标是将 demolabconfig.json 中的“name”键替换为存储在文本文件中的名称。
"name": "Node1" must be replaced as "name":"Tom-cat"
];
.....
.....
],
"name": "Node2" must be replaced as "name":"Lucky-worm"
];
.....
.....
],
"name": "Node3" must be replaced as "name":"Wom-bat"
为关键“节点”完成索引:.lab.racks[].nodes[$i].name
代码:
readarray -t array < newhostnames.txt
array=("${array[@]:1}")
array_length=${#array[@]}
for((i=0;i<${array_length};i++));
do
declare -x NEW_NODENAME
OLD_NODENAME=$(jq -r ".lab.racks[].nodes[$i].name" demolabconfig.json)
echo "$OLD_NODENAME"
NEW_NODENAME="${array[i]}"
echo "$NEW_NODENAME"
jq ".lab.racks[].nodes[$i].name=env.NEW_NODENAME" demolabconfig.json > newdemolabconfig.json
done
但代码最后只替换了最后一个 $i 的一个值,即最后一个 key_value 对。所有其他前面的节点保留与原始 JSON 文件中相同的名称。
如果值已经更新,我已经尝试使用 if 语句来中断循环,因此它不会从旧的 demolabconfig.json 文件中重写。但这也行不通!
if [[ "$OLD_NODENAME" -ne "$NEWNODENAME" ]]; then
jq ".lab.racks[].nodes[$i].name=env.NEW_NODENAME" demolabconfig.json > newdemolabconfig.json
else
break
fi
这个 if 循环是用 while 循环而不是 for 编写的。这会将姓氏替换为 null。
请建议我如何修复此错误并改进我的代码。谢谢:)
【问题讨论】:
-
首先,
-ne严格用于整数比较;使用!=进行字符串比较。但是,您应该发布示例输入和预期输出,因为几乎可以肯定有一种方法可以通过调用jq来完成此操作,而不是在bash中进行迭代。 (在bash中有一种更简洁的方法来进行迭代,但这里的主题还不足以作为答案发布。{ read; while IFS= read -r new_nodename; do ...; done; } < newhostnames.txt。 -
哦,忽略我的循环评论;现在,你仍然需要
i来匹配你的本地数组和 JSON 数组。 -
您好,谢谢!我已经编辑了这个问题,我希望这可以更好地说明我想要完成的工作。