返回 yq 中 `.[]` 之后的 1 个文档

问题描述 投票:0回答:1

案例1

有输入

- groupx:
- groupy:

yq 表达式

length
计算为
2

案例2

有输入

groupx:
groupy:

yq 表达式

length
also 计算为
2

案例 3 - 使用 splat (
.[]
) 将 case1 转换为 case2

首先,我们将案例 1 的输入转换为案例 2:

$ yq '.[]' case1.yaml

groupx:
groupy:

我们注意到这与

case2.yaml

的输出相同

如果我想用 case2 的表达式扩展这个表达式,我不会得到相同的输出,而是得到以下结果:

$ yq '.[] | length' case1.yaml
1
1

如果我添加第二个 yq 过程,我 do 会得到与 case2 相同的结果:

$ yq '.[]' case1.yaml | yq 'length'
2

问题

为什么 yq 的 splat 运算符使结果有效地成为 yaml 多文档?这没有意义,因为相同的输出再次作为 yq 的输入,不会产生多文档。

如果这是预期行为,您可以在使用

.[]
后返回到单个文档而不启动新的 yq 流程吗?

yaml yq
1个回答
0
投票

案例 1 是一个带有 seq(数组)的单个文档,其中包含两个映射(对象),每个映射都只有一个键(字段)。

案例 2 是一个带有映射(对象)的单个文档,其中包含两个键(字段)。

.[]
应用于任何一种情况都会破坏文档的顶级类型(第一种情况下的 seq,第二种情况下的映射),并在 two 文档中产生结果(对于这两种情况)(第一个有两个映射,第二个有两个映射)第二个两个(空)值)。

因此,在同一个过滤器中将

length
应用于该结果总是会产生两个数字(在第一种情况下都是
1
,因为你有两个映射,每个映射都包含一个键,而在第二种情况下,两个
0
因为你有两个标量不包含任何内容的值)。

但是,将

length
应用于另一个过滤器中的结果会重新评估输入。现在,在第一种情况下,两个单项映射折叠成一个包含两个项的映射,因此总体结果为
2
。在第二种情况下,标量值无法进一步折叠,因此结果保持不变(两个数字,都是
0
)。

无论这是有意还是无意,我都无法代表开发商发言。但我可以断言,这种偏差仅适用于 mikefarah/yq,不适用于 kislyuk/yq,后者始终将输入视为两个文档,因为它主动打印文档分隔符。 (虽然 mikefarah/yq 有一个

--no-doc
(或
-N
)选项“不打印文档分隔符”,但这似乎是默认应用的——使用版本 v4.34.2 和 v4.40.5 进行测试)。

如果这是预期行为,您可以在使用

.[]
后返回到单个文档而不启动新的 yq 流程吗?

当然。您可以将解构后的项目收集为单个项目,但其实现取决于它应该具有什么类型。

如果您希望它是结果文档的序列,请将过滤器括在括号中以将项目收集到其中。所以

.[] | … | length
将变成
[.[] | …] | length
并且应该产生
2
。实际上,您可以使用
[.[] | …]
快捷方式
map(…)

如果您希望它成为一个地图(就像它通过两次调用折叠一样),您可以使用

ireduce
迭代地将所有项目附加到最初为空的地图:
(.[] | …) as $i ireduce ({}; . + $i) | length
。 (旁注:使用 kislyuk/yq,您可以使用
add
过滤器,可以将一系列映射折叠成单个映射。)

© www.soinside.com 2019 - 2024. All rights reserved.