英文:
How to replace value recursively in yq depend on key and value type?
问题
以下是您要求的翻译:
我希望我能使用 yq 递归地迭代一个 YAML,找到所有键值对,其键是“image”,值的类型是“string”(!!str),然后在原始值前添加一个前缀。
输入:
``` yaml
serving:
template:
image: "docker.io/serving"
custom:
template:
image:
type: string
description: "..."
eventing:
image: "docker.io/eventing"
如果其值的类型递归为string
(!!str),则将前缀private.io/
添加到所有image
字段。
预期输出:
serving:
template:
image: "private.io/docker.io/serving"
custom:
template:
image:
type: string
description: "..."
eventing:
image: "private.io/docker.io/eventing"
对于等效的 JSON,我可以使用walk
运算符来执行这样的操作:
jq 'walk(if type == "object" and has("image") and (.image|type) == "string" then .image = "private.io/" + .image else . end)' input.json
是否有类似walk
的等效运算符,我已经尝试了..
运算符:
yq '.. | select(tag == "!!str" and key == "image") |= "private.io/" + . ' input.json
但是这个命令会向 YAML 中添加一些条目,导致:
serving:
template:
image: "private.io/docker.io/serving"
custom:
template:
image:
type: string
description: "..."
eventing:
image: "private.io/docker.io/eventing"
template:
image: "private.io/docker.io/serving"
image: "private.io/docker.io/serving"
private.io/docker.io/serving
template:
image:
type: string
description: "..."
image:
type: string
description: "..."
type: string
description: "..."
string
...
image: "private.io/docker.io/eventing"
private.io/docker.io/eventing
有没有任何想法或解决方法?谢谢,真诚的~
英文:
I wish I could use yq to iterate a yaml recursively, find all key-value pairs, whose key is image
and value type is string
(!!str), then add a prefix to the original value.
Input:
serving:
template:
image: "docker.io/serving"
custom:
template:
image:
type: string
description: "..."
eventing:
image: "docker.io/eventing"
Add a prefix private.io/
to all image
field if its value type is string
(!!str) recursively.
Expected output:
serving:
template:
image: "private.io/docker.io/serving"
custom:
template:
image:
type: string
description: "..."
eventing:
image: "private.io/docker.io/eventing"
For a equivalent json, I can use the walk
operator to do such thing:
jq 'walk(if type == "object" and has("image") and (.image|type) == "string" then .image = "private.io/" + .image else . end)' input.json
Is there any equivalent operator like walk
, I have tried the ..
operator
yq '.. | select(tag == "!!str" and key == "image") |= "private.io/" + . ' input.json
But this command add some entries to the yaml, result in:
serving:
template:
image: "private.io/docker.io/serving"
custom:
template:
image:
type: string
description: "..."
eventing:
image: "private.io/docker.io/eventing"
template:
image: "private.io/docker.io/serving"
image: "private.io/docker.io/serving"
private.io/docker.io/serving
template:
image:
type: string
description: "..."
image:
type: string
description: "..."
type: string
description: "..."
string
...
image: "private.io/docker.io/eventing"
private.io/docker.io/eventing
Any ideas or walk around ? Thanks, sincerely~
答案1
得分: 1
有的,你差不多就快做到了。只需在括号内保留上下文:
yq '(.. | select(key == "image" and type == "!!str")) |= "private.io/" + .'
serving:
template:
image: "private.io/docker.io/serving"
custom:
template:
image:
type: string
description: "..."
eventing:
image: "private.io/docker.io/eventing"
已在 mikefarah/yq v4.31.1 上进行测试
注意:使用 kislyuk/yq 或 itchyny/gojq 你也可以在你的 YAML 输入上使用原始的 walk
过滤器。这两个工具都可以使用正确的 jq 语法处理 YAML 文件。
yq -y 'walk(
if type == "object" and has("image") and (.image|type) == "string"
then .image |= "private.io/" + . else . end
)'
# 或者
gojq --yaml-input --yaml-output 'walk(
if type == "object" and has("image") and (.image|type) == "string"
then .image |= "private.io/" + . else . end
)'
英文:
There is, and you almost had it. Just set parentheses to retain the context:
yq '(.. | select(key == "image" and type == "!!str")) |= "private.io/" + .'
serving:
template:
image: "private.io/docker.io/serving"
custom:
template:
image:
type: string
description: "..."
eventing:
image: "private.io/docker.io/eventing"
Tested with mikefarah/yq v4.31.1
Note: With kislyuk/yq or itchyny/gojq you can also use your original walk
filter on your YAML input. Both tools can process YAML files using proper jq syntax.
yq -y 'walk(
if type == "object" and has("image") and (.image|type) == "string"
then .image |= "private.io/" + . else . end
)'
# or
gojq --yaml-input --yaml-output 'walk(
if type == "object" and has("image") and (.image|type) == "string"
then .image |= "private.io/" + . else . end
)'
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论