我试图使用jq
(和yq)来删除单个Kubernetes资源。我想我可以用del
来做这个,但它留下了一个null
。
$ cat test.yaml | yq -y '. | del(select(.kind == "Namespace" and .metadata.name == "bar"))'
apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
--- null
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}
我的测试数据:
$ cat test.yaml
apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: bar
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}
我如何得到这个输出?
apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}
我从语法中假设您正在使用kislyuk yq。
del
不是适合这项工作的工具。del
接受一个N个值的流,并返回一个N个修改值的流。在你的例子中,它接受三个值的流并返回三个值的流。您可以观察到,它使第一个和最后一个对象保持不变,但将第二个对象替换为null
。对于它输入的每个值,它计算其参数过滤器以决定如何更改该值—该过滤器发出的每个位置都将被删除。您已经提供了一个select
过滤器作为它的参数。一个select过滤器接受一个值流,并发出一个流,其中一些值未经修改,同时丢弃其他值,这取决于它的过滤器参数。(实际上,它比这更复杂一点——如果你给它传递一个返回多个值的过滤器,它实际上可以发出比它接收到的更多的值,但这在这里不相关。)
在本例中,您的select
过滤器对第一个对象不返回任何内容,因为它不匹配,因此del
不更改任何内容。对于第二个对象,select
过滤器不匹配该对象,因此del
过滤器等同于del(.)
。当您传递给del
的过滤器不选择对象(或数组)中的键(或索引),而是整个事情时,文档并不是非常清楚会发生什么,但显然实践中的行为是它将其替换为null
。
如果你遵循这个解释,你可能会看到这是怎么回事。select
已经是你想要的工具!这里根本不需要del
。select
是只保留对象流中的部分的机制。试一试:
$ cat ~/scratch/test.yaml | yq -y 'select(.kind != "Namespace" or .metadata.name != "bar")'
apiVersion: v1
kind: Namespace
metadata:
name: foo
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
name: baz
spec: {}
status: {}
您可以使用gojq, jq的Go实现:
gojq --yaml-input --yaml-output 'select(.metadata.name != "bar")' test.yaml