合并两个 yaml 文件,以便列表在必要时具有额外的值
merge two yaml files so list has extra values if necessary
在我的 shell 脚本中,有一个命令使用 yaml 文件的部分,我希望这个 yaml 文件根据 [=] 中可访问的变量值略有不同22=]脚本。
yaml文件如下:
name: John
friends:
- friendName: Bob
family:
extended:
cousins:
- Sarah
- Jane
- Tom
age: 12
然而,根据上述变量的值,我可能还希望 yaml 文件如下(即向 cousins
列表添加更多值):
name: John
friends:
- friendName: Bob
family:
extended:
cousins:
- Sarah
- Jane
- Tom
- Arthur
- Michael
- Frank
age: 12
我了解 yaml 文件不支持条件语句,理想情况下我不希望在 yaml 文件中重复内容。有没有办法合并两个 yaml 文件,这样如果两个文件中存在相同的列表,它们就会合并(从而实现我想要的向 cousins
列表添加更多值的目标?
Multiply 可以使用变体 *+
来实现,它连接序列:
yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' file1.yaml file2.yaml
鉴于输入:
# file1.yaml
---
- one
- two
- three
...
# file2.yaml
---
- three
- four
- five
你会得到
- one
- two
- three
- three
- four
- five
请注意 concatenate 意味着两个列表中存在的任何值都会重复。您对此无能为力,这就是列表的工作方式。如果您不想重复项目,则必须改用具有该语义的集合。在 YAML 中,您通过提供没有值的映射来定义集合:
# file1.yaml
---
? one
? two
? three
...
# file2.yaml
---
? three
? four
? five
对这些应用相同的操作会给你
one:
two:
three:
four:
five:
(是的,yq
无法在此处保留 ?
语法,这对纯集合更好,但语义相同)
但是如果最终的 YAML 必须包含列表怎么办?好吧,我们最初需要集合来进行合并,但之后我们可以将它们转换为序列,例如这些输入:
# file1.yaml
---
some:
list:
? one
? two
? three
...
# file2.yaml
---
some:
list:
? three
? four
? five
使用此命令处理:
yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1) | .some.list |= keys' file1.yaml file2.yaml
会给你:
some:
list:
- one
- two
- three
- four
- five
但是因为我们可以动态修改数据,所以我们可以也制作它,这样我们就可以输入序列,这些序列将被转换为集合,组合,然后重新-写成序列。有了这个输入
# file1.yaml
---
some:
list:
- one
- two
- three
...
# file2.yaml
---
some:
list:
- three
- four
- five
和这个命令
yq eval-all '
(select(fileIndex == 0) | .some.list |= ((.[] | {.: ""}) as $item
ireduce ({}; . * $item)))
*+
(select(fileIndex == 1) | .some.list |= ((.[] | {.: ""}) as $item
ireduce ({}; . * $item)))
| .some.list |= keys' file1.yaml file2.yaml
你得到
some:
list:
- one
- two
- three
- four
- five
现在的问题是:你能证明你的任务如此复杂吗?
在我的 shell 脚本中,有一个命令使用 yaml 文件的部分,我希望这个 yaml 文件根据 [=] 中可访问的变量值略有不同22=]脚本。
yaml文件如下:
name: John
friends:
- friendName: Bob
family:
extended:
cousins:
- Sarah
- Jane
- Tom
age: 12
然而,根据上述变量的值,我可能还希望 yaml 文件如下(即向 cousins
列表添加更多值):
name: John
friends:
- friendName: Bob
family:
extended:
cousins:
- Sarah
- Jane
- Tom
- Arthur
- Michael
- Frank
age: 12
我了解 yaml 文件不支持条件语句,理想情况下我不希望在 yaml 文件中重复内容。有没有办法合并两个 yaml 文件,这样如果两个文件中存在相同的列表,它们就会合并(从而实现我想要的向 cousins
列表添加更多值的目标?
Multiply 可以使用变体 *+
来实现,它连接序列:
yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' file1.yaml file2.yaml
鉴于输入:
# file1.yaml
---
- one
- two
- three
...
# file2.yaml
---
- three
- four
- five
你会得到
- one
- two
- three
- three
- four
- five
请注意 concatenate 意味着两个列表中存在的任何值都会重复。您对此无能为力,这就是列表的工作方式。如果您不想重复项目,则必须改用具有该语义的集合。在 YAML 中,您通过提供没有值的映射来定义集合:
# file1.yaml
---
? one
? two
? three
...
# file2.yaml
---
? three
? four
? five
对这些应用相同的操作会给你
one:
two:
three:
four:
five:
(是的,yq
无法在此处保留 ?
语法,这对纯集合更好,但语义相同)
但是如果最终的 YAML 必须包含列表怎么办?好吧,我们最初需要集合来进行合并,但之后我们可以将它们转换为序列,例如这些输入:
# file1.yaml
---
some:
list:
? one
? two
? three
...
# file2.yaml
---
some:
list:
? three
? four
? five
使用此命令处理:
yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1) | .some.list |= keys' file1.yaml file2.yaml
会给你:
some:
list:
- one
- two
- three
- four
- five
但是因为我们可以动态修改数据,所以我们可以也制作它,这样我们就可以输入序列,这些序列将被转换为集合,组合,然后重新-写成序列。有了这个输入
# file1.yaml
---
some:
list:
- one
- two
- three
...
# file2.yaml
---
some:
list:
- three
- four
- five
和这个命令
yq eval-all '
(select(fileIndex == 0) | .some.list |= ((.[] | {.: ""}) as $item
ireduce ({}; . * $item)))
*+
(select(fileIndex == 1) | .some.list |= ((.[] | {.: ""}) as $item
ireduce ({}; . * $item)))
| .some.list |= keys' file1.yaml file2.yaml
你得到
some:
list:
- one
- two
- three
- four
- five
现在的问题是:你能证明你的任务如此复杂吗?