【问题标题】:Is it possible to insert an element into a middle of array in YAML using YQ?是否可以使用 YQ 将元素插入 YAML 中的数组中间?
【发布时间】:2022-11-13 07:04:17
【问题描述】:

我有一个像这样的 YAML 文档

    
services:
  - name: newlogd
    image: NEWLOGD_TAG
    cgroupsPath: /eve/services/newlogd
    oomScoreAdj: -999
  - name: edgeview
    image: EDGEVIEW_TAG
    cgroupsPath: /eve/services/eve-edgeview
    oomScoreAdj: -800
  - name: debug
    image: DEBUG_TAG
    cgroupsPath: /eve/services/debug
    oomScoreAdj: -999
  - name: wwan
    image: WWAN_TAG
    cgroupsPath: /eve/services/wwan
    oomScoreAdj: -999

我需要在给定元素之后插入一个新对象,例如名称 == “edgeview”。所以输出看起来像这样


services:
  - name: newlogd
    image: NEWLOGD_TAG
    cgroupsPath: /eve/services/newlogd
    oomScoreAdj: -999
  - name: edgeview
    image: EDGEVIEW_TAG
    cgroupsPath: /eve/services/eve-edgeview
    oomScoreAdj: -800
  - name: new_element_name
    image: new_element_image
  - name: debug
    image: DEBUG_TAG
    cgroupsPath: /eve/services/debug
    oomScoreAdj: -999
  - name: wwan
    image: WWAN_TAG
    cgroupsPath: /eve/services/wwan
    oomScoreAdj: -999

我在 YQ 文档中找不到任何关于它的信息。甚至可以使用YQ吗?

更新:我正在使用 YQ https://github.com/mikefarah/yq 版本 4.28.1。我不知道有几个同名的工具。

【问题讨论】:

标签: yaml yq


【解决方案1】:

使用 YAML 处理器yq

yq --arg insertAfter edgeview -y '
   limit(1; .services | to_entries[] | select(.value.name == $insertAfter) | .key + 1) as $idx
   | .services |= .[0:$idx] +
                  [{name: "new_element_name", image: "new_element_image"}] +
                  .[$idx:]'

第一行确定后面要插入的元素的索引,存入$idx。 如果您有多个同名元素,则仅使用第一个匹配项 (limit)。 在接下来的过滤步骤中,$idx 用于拆分数组并将新元素插入到所需位置。

输出

services:
  - name: newlogd
    image: NEWLOGD_TAG
    cgroupsPath: /eve/services/newlogd
    oomScoreAdj: -999
  - name: edgeview
    image: EDGEVIEW_TAG
    cgroupsPath: /eve/services/eve-edgeview
    oomScoreAdj: -800
  - name: new_element_name
    image: new_element_image
  - name: debug
    image: DEBUG_TAG
    cgroupsPath: /eve/services/debug
    oomScoreAdj: -999
  - name: wwan
    image: WWAN_TAG
    cgroupsPath: /eve/services/wwan
    oomScoreAdj: -999

【讨论】:

  • 从这个答案切换到 yq 后,我可以完成我需要的所有任务。我不得不稍微更改其他查询,因为语法略有不同。我发现基于 Python 的 YQ 语法更加清晰。谢谢!
  • 两种实现方式都有其优点和局限性。如果您更频繁地使用 json / yaml,那么了解这两者是很好的。但是这个任务我无法用yq 解决,因为我发现拼接数组中有一个error
【解决方案2】:

在 mikefarah/yq (v.4.30+) 你可以这样做:

yq '.services |= (
    (.[] | select(.name == "edgeview") | key + 1) as $pos |
    .[:$pos] + 
    [{"name": "new_element_name", "image": "new_element_image"}] +
    .[$pos:])' examples/data1.yaml

解释:

  • 您想更新“服务”数组,所以我们有“.services |=”
  • 找到更新数组的位置,这是一个接一个的名称为“edgeview”的位置。 Splat 数组,找到匹配项,获取其索引并添加一个(.[] | select(.name == "edgeview") | key + 1)
  • 将该位置的值分配给 $pos。
  • 现在您可以使用数组切片运算符来重建包含新元素的数组。
  • 将数组的开头[:$pos]和新元素{"name": "new_element_name"}添加到数组的结尾[$pos:]

免责声明:我写了 yq

【讨论】:

    猜你喜欢
    • 2013-01-23
    • 2021-05-14
    • 2020-06-02
    • 2020-09-17
    • 2013-02-12
    • 2022-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多