You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

BASH脚本迭代替换JSON节点name值失败求助

嘿,刚接触bash、jq和JSON两周就啃这个任务,确实有点挠头——我完全懂你现在的挫败感,咱们一步步把这个问题捋顺、解决掉!

问题根源先搞清楚

你之前的脚本之所以只最后一个节点生效,核心原因是每次循环都从原始的demolabconfig.json读取内容:比如第一次循环改了第一个节点,写入文件;但第二次循环又重新读原始文件,相当于把第一次的修改覆盖了,从头改第二个节点……最后自然只有最后一次的修改能保留。如果循环次数超过了nodes的数量,还会出现null的情况(因为jq会给不存在的节点赋值)。

高效解决方法:让jq一次性处理所有替换

最好的思路是把所有主机名传给jq,让它一次性完成所有节点的替换,避免循环读写文件导致的覆盖问题。下面是具体的脚本和解释:

完整修复脚本

# 先把newhostnames.txt里的主机名逐行存入数组,避免空格等特殊字符干扰
mapfile -t hostnames < newhostnames.txt

# 用jq一次性完成所有nodes的name替换,输出到新文件(避免直接覆盖原始文件)
jq --argjson hostnames "$(printf '%s\n' "${hostnames[@]}" | jq -R . | jq -s .)" '
  .lab.racks[] |= (
    .nodes |= (
      range(0; length) as $i |
      .[$i].name = ($hostnames[$i] // .[$i].name)
    )
  )
' demolabconfig.json > updated_demolabconfig.json

脚本细节解释

  1. mapfile读取主机名:把newhostnames.txt的每一行存入hostnames数组,完美处理带空格的主机名(比如Tom-catLucky-worm)。
  2. 转成JSON数组传给jq:用printf配合jq把bash数组转成jq能识别的JSON数组,存在$hostnames变量里。
  3. jq核心替换逻辑
    • 遍历每个rack下的nodes列表
    • 用索引$i对应$hostnames数组的第$i个元素,替换name
    • //是jq的空值合并运算符:如果主机名数量比nodes少,对应节点会保留原来的name,不会变成null
  4. 输出到新文件:直接输出到updated_demolabconfig.json,调试时不会破坏原始文件,确认没问题后再替换原文件即可。

额外注意事项

  • 确保newhostnames.txt里的主机名数量和JSON中所有nodes的总数量匹配:如果主机名多了,多出来的会被忽略;如果少了,剩余节点保留原name(就是脚本里//的作用)。
  • 如果你想直接覆盖原始文件,可以用sponge工具(需要先安装moreutils包),避免临时文件的麻烦:
    ...(前面的代码不变)
    )' demolabconfig.json | sponge demolabconfig.json
    

内容的提问来源于stack exchange,提问作者Akshatha Nadig

火山引擎 最新活动