I have the following structure in yml:
我在YML中有以下结构:
metadata:
name: nws-bot
version: 0.1.0
jobs:
- name: name1
script: job1.sh
schedule: 0 20 * * *
- name: name2
script: job2.sh
schedule: 0 22 * * *
I'm trying to create a structure like this:
我正试着创造一个这样的结构:
name1~job1.sh;name2~job2.sh
The job name and script are separated by a ~, and the jobs are separated by a ;.
作业名称和脚本用~分隔,作业用;分隔。
I can get this to work using
我可以使用以下命令使其正常工作
yq '.metadata.jobs[] | [[.name, .script] | join("~")]' project.yml | yq '. | join(";")'
However I wonder if it can be done with a single yq
expression, instead of piping to yq
a second time.
然而,我想知道是否可以用一个yq表达式来完成,而不是通过管道再次使用yq。
更多回答
优秀答案推荐
Iterating with .metadata.jobs[]
(which is a shortcut for .metadata.jobs | .[]
) also destructures the array into its individual items. To re-capture them (meanwhile modified with the first join
) back into an array (to be applied to the second join
) necessitates the collecting array to be superordinate to the destructuring. Thus, move the iteration inside of it, i.e. pull the opening bracket up front (with the initial traversal to .metadata.jobs
included or excluded at your preference):
使用.metadata.Jobs[](.metadata.Jobs|.[]的快捷方式)进行迭代也会将数组分解为其单独的项。要将它们重新捕获(同时使用第一个联接进行修改)回到一个数组中(应用于第二个联接),收集数组必须高于析构。因此,将迭代移到其中,即将左方括号拉到前面(根据您的喜好包括或排除对.metadata.Jobs的初始遍历):
yq '.metadata.jobs[] | [[.name, .script] | join("~")]' project.yml | yq 'join(";")'
# ╭──────────────────╯
yq '[.metadata.jobs[] | [.name, .script] | join("~")] | join(";")' project.yml
# ╰────────────────╮
yq '.metadata.jobs | [.[] | [.name, .script] | join("~")] | join(";")' project.yml
Actually, having [.[] | …]
is what map(…)
does: applying a filter to the items of an array while retaining the array structure. Using named filters can make code more descriptive and facilitate its readability. Alternatively, there's also the update operator |=
which can be used to alter the items of a (generally deeper) structure without destructuring it. In both cases, however, your context here needs to be the array itself, so the initial traversal to .metadata.jobs
must be completed prior to their usage (e.g. .metadata.jobs[] |= …
would in excess also retain the top level objects, making the second join
eventually fail).
实际上,拥有[.[]|…]是什么地图(…)执行:在保留数组结构的同时将筛选器应用于数组的项。使用命名筛选器可以使代码更具描述性,并有助于其可读性。或者,还有UPDATE操作符|=,它可用于在不破坏结构的情况下更改(通常更深)结构中的项。但是,在这两种情况下,您的上下文都需要是数组本身,因此必须在使用.metadata.job之前完成对.metadata.job的初始遍历(例如.metadata.Jobs[]|=…会过多地保留顶级对象,从而使第二次联接最终失败)。
yq '.metadata.jobs | map([.name, .script] | join("~")) | join(";")' project.yml
# or
yq '.metadata.jobs | .[] |= ([.name, .script] | join("~")) | join(";")' project.yml
Given your sample input, all of them output:
给出您的样例输入,所有它们都输出:
name1~job1.sh;name2~job2.sh
更多回答
我是一名优秀的程序员,十分优秀!