yq的splat(.[])运算符多文档行为疑问及单文档回归方法
yq中splat运算符的多文档行为及单文档回归方案
问题原因解析
1. .[]为何等效于多文档输出
在mikefarah/yq中,splat运算符.[]遍历数组时,每个数组元素都会被当作独立的YAML文档输出。默认多文档用---分隔,但如果元素是简单映射,输出时可能省略分隔符,不过yq内部仍会按多文档处理。
所以执行yq '.[] | length' case1.yaml时,实际是对两个单键映射分别计算长度,每个映射的长度都是1,因此输出两个1。
2. 管道后为何被识别为单文档
当把.[]的输出管道给另一个yq进程时,yq会遵循YAML规范解析:没有---分隔符的连续键值对属于同一个文档。原本的两个独立映射会被合并成一个包含两个键的单映射文档,此时计算length自然得到2。
单进程内的解决方案
要在不启动新yq进程的前提下,将.[]遍历后的元素合并回单文档,核心是把分散的映射元素合并为一个完整映射,有两种常用方式:
方式1:用reduce逐步合并映射
通过reduce遍历数组元素,把每个映射合并到初始空映射中:
yq 'reduce .[] as $elem ({}; . += $elem) | length' case1.yaml
执行后直接输出2,和案例2结果一致。
方式2:用add合并数组内的映射
对于包含多个映射的数组,add操作会自动将所有映射合并为一个(键不冲突时),可以简化为:
yq '. | add | length' case1.yaml
这个表达式直接对原数组执行合并,效果和先.[]再合并相同,最终结果也是2。
如果必须先通过.[]做中间处理,再合并回单文档,可以调整为:
yq '.[] | [你的中间处理逻辑] | reduce . as $elem ({}; . += $elem) | length' case1.yaml
内容的提问来源于stack exchange,提问作者hbogert
相关产品推荐
相关产品推荐

