使用 mike Farah 的 yq 将内容添加到 yaml 文件

使用 mike Farah 的 yq 将内容添加到 yaml 文件

这是一个基本问题,但我正在努力完成这项工作,因为我没有 bash 经验。

假设我有一个目录directory_1,在这个目录中我有cen1.yaml 和cen2.yaml。 cen1.yaml 有一个名为 name 的字段

name:xxxx

并且 cen2.yaml 的内容可能会有所不同(示例)

service:ser1
image:
  field1:field1
  field2:field2
.
.
.

在第一次迭代中,我有一个空的 Final.yaml。但我希望此文件具有 cen1.yaml 中的名称,并且 cen2 中的所有内容都应采用这样的名称。

xxxx:
  service:ser1
  image:
    field1:field1
    field2:field2
  .
  .
  .

接下来,我将克隆另一个具有相同文件名的目录(cen1.yaml 和 cen2.yaml)。 Cen1.yaml 再次具有名称字段

name:another

并且 cen2.yaml 将有自己的内容。

tv:lcd
name:
  field1:field1
  field2:field2
.
.
.

现在我需要附加到已存在的文件中并保持相同的结构

xxxx:
  service:ser1
  image:
    field1:field1
    field2:field2
  .
  .
  .
another
  tv:lcd
  mount:
    field1:field1
    field2:field2
  .
  .
  .

因此,我需要一个适用于两种情况的命令:当文件为空并且它写入第一次迭代时,或者当文件已经有内容并且它将附加到它时。我怎样才能实现这个目标?

答案1

以下是 Mike Farah 的表达式,yq它从 中加载名称cen1.yaml并将其放入内部yq变量中$name。然后,它创建一个新的 YAML 文档并加载cen2.yaml到其中,使用以下给出的密钥$name

load("cen1.yaml").name as $name | .[$name] = load("cen2.yaml")

我们可以使用它来循环多个子目录,yq在每个子目录中应用,并在 中收集输出final.yaml。该代码假设目录全部匹配文件名通配模式directory_*

for dir in directory_*; do
(
    cd "$dir" &&
    yq -n 'load("cen1.yaml").name as $name | .[$name] = load("cen2.yaml")'
)
done >final.yaml

我们使用-nwith 是yq因为我们不使用命令行上给出的任何文件。

鉴于您问题中的数据(通过删除虚线并在每个后面插入空格进行更正:),这将生成以下 YAML 文件:

xxxx:
  service: ser1
  image:
    field1: field1
    field2: field2
another:
  tv: lcd
  name:
    field1: field1
    field2: field2

如果所有目录不能同时可用,您可以final.yaml通过向文件附加位来构建文件:

rm -f final.yaml

# Get directory_1, and then...
(
    cd directory_1 &&
    yq -n 'load("cen1.yaml").name as $name | .[$name] = load("cen2.yaml")'
) >>final.yaml

# Get directory_2, and then...
(
    cd directory_2 &&
    yq -n 'load("cen1.yaml").name as $name | .[$name] = load("cen2.yaml")'
) >>final.yaml

# etc.

...本质上是手动运行循环的每次迭代,并将输出附加到每个步骤的结果文件中。


同样的事情,但是使用 Andrey Kislyuk 的yq( 的包装jq):

for dir in directory_*; do
(
    cd "$dir" &&
    yq -n -y 'input.name as $name | .[$name] = inputs' cen1.yaml cen2.yaml
)
done >final.yaml

相关内容