这是一个基本问题,但我正在努力完成这项工作,因为我没有 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
我们使用-n
with 是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