将 yaml 中的值替换为 name : xxx with bash

Replace value in yaml if name : xxx with bash

我想更改 yaml 文件 value 基于 name:

示例:

spec:
  containers:
    - name: app1
      image: imageurl.com
      command: []
      env:
      - name: MONGO_HOST
        value: localhost

在这里您可以看到我们为 mongo 主机添加了一个环境。现在使用 BASH 我想根据 if - name: MONGO_HOST set value: 172.16.87.98

等条件更改 MONGO_HOST value

您可以使用这个 awk:

awk '/^[ \t]*- *name: *MONGO_HOST[ \t]*$/{p=NR}
p && NR==p+1{sub(/value:.+/, "value: 172.16.87.98")} 1' file.yml

spec:
  containers:
    - name: app1
      image: imageurl.com
      command: []
      env:
      - name: MONGO_HOST
        value: 172.16.87.98

但是,请记住,通常最好为此使用专用的 yaml 解析器。

kislyuk/yq 是一个 YAML 语法感知解析器,它使用 jq 作为其 JSON 处理器。 yq 获取 YAML 输入,将其转换为 JSON,并将其提供给 jq

过滤器,'..'下的部分应用在JSON对象上,形成IP更新后的结果JSON并转换回YAML格式,因为 -y 参数。

yq -y '(.spec.containers[].env[]|select(.name == "MONGO_HOST").value)|="172.16.87.98"' yaml  

安装和使用非常简单,可在 yq: Command-line YAML/XML processor

中找到

您可以像 sed -i 一样使用就地编辑选项 -i 来避免使用 yq -yi '...'

重定向到临时文件

mikefarah/yq

mikefarah/yq 是 YAML 解析器的 Go 实现,自 v4 以来采用了类似于 jq 的 DSL。所以使用相同的方法,可以做到

yq e '(.spec.containers[].env[]|select(.name == "MONGO_HOST").value) |= "172.16.87.98"' yaml

Sed 需要知道该文件上是否确实存在 MONGO_HOST,因此 grep 进入了解决方案。

 if grep -Fq -- "- name: MONGO_HOST" file.yaml; then
   sed 's/^\([[:space:]]\+value:\).*/ 172.16.87.98/' file.yaml
 fi

if 语句来自 shell,它检查 grep 是否真的找到 pattern/regexp 并在这种情况下执行 sed

-F 表示 grep 正在查找固定字符串,而不是 BRE(基本正则表达式)或 ERE(扩展正则表达式)

-q 表示安静或静音输出。

-- 表示选项结束,因为选项通常以破折号开头 - -- grep 之后的任何内容都不再将其视为选项

如果有 is/are 个以上的字符串 value: 正则表达式 file.yml sed 将全部替换。但正如建议的那样,已经为 parsing/editing yaml 文件使用了正确的工具。

编辑:正如 Ranvijay Sachan 所指出的,sed 可以检查是否存在模式并替换以下行。

使用基于命令的文件编辑器ed

printf '%s\n' '/MONGO_HOST/+1s/^\([[:space:]]\+value:\).*/ 172.16.87.98/' ,p w | ed -s file.yaml