YAML/YQ - 删除具有包含特定属性匹配项的子部分的部分
YAML/YQ - remove sections that have sub-sections containing a particular attribute match
我正在尝试使用 mikefarah 的 yq
远程访问 yaml
文件的部分,这些部分的子部分具有特定属性匹配。
更具体地说,假设我们有以下 OpenAPI 文件:
openapi: 3.0.0
protocol: https
tags:
- description: Sample API
name: Sample Echo API
info:
title: UUID generator based on httpbin.org
version: 1.0.3
paths:
/uuid:
get:
responses:
"200":
description: A UUID4.
summary: Return a UUID4.
tags:
- UUID Ops
/uuid/{uuid}:
delete:
parameters:
- in: path
name: uuid
required: true
schema:
type: string
responses:
"200":
description: Deleted okay.
summary: This endpoint makes no sense.
tags:
- UUID Ops
- Experimental
/delay/{delay}:
get:
parameters:
- in: path
name: delay
required: true
schema:
type: integer
responses:
"200":
description: Returns a delayed response
summary: Returns a delayed response
tags:
- Delayed Response
- Experimental
servers:
- url: https://httpbin.org/
我想删除所有带有“实验”标签的 API 端点,所以基本上生成的文件是:
openapi: 3.0.0
protocol: https
tags:
- description: Sample API
name: Sample Echo API
info:
title: UUID generator based on httpbin.org
version: 1.0.3
paths:
/uuid:
get:
responses:
"200":
description: A UUID4.
summary: Return a UUID4.
tags:
- UUID Ops
servers:
- url: https://httpbin.org/
我苦苦挣扎的地方是为 yq
命令找到正确的 'level' 以这种方式工作。
例如,我知道我可以用几种不同的方式显示所有标签:
yq eval '.paths[]?[]?.tags?' openapi.yaml
或
yq eval '.. | select(. == "Experimental")' openapi.yaml
但是当我尝试如下操作时,根据标签删除父部分(即实际的 API 块):
yq eval '.paths | del(.. | select(. == "Experimental"))' openapi.yaml
或
yq eval '.paths |= with_entries(del(select(.. | select(. == "Experimental"))) )' openapi.yaml
它所做的只是删除特定的 Experimental
标签,而不是实际的 API 块。
请问我做错了什么?
对于 mikefarah/yq,这有点棘手,但您可以使用 with_entries
和 contains
方法来实现您想要的结果
yq e '
.paths |=
with_entries( select( .value[].tags | contains(["Experimental"] ) | not ) )' yaml
使用 with_entries,您的每个地图元素都被转换为 key/value 对,并且通过使用特殊符号 .value[]
,您可以绕过顶级键 - /uuid
, /uuid/{uuid}
并直接在 tags
上应用您的过滤器
使用 contains,我们能够仅过滤仅包含 "Experimental"
的必要对象,并使用 not
否定该条件以获得您想要的结果。
我正在尝试使用 mikefarah 的 yq
远程访问 yaml
文件的部分,这些部分的子部分具有特定属性匹配。
更具体地说,假设我们有以下 OpenAPI 文件:
openapi: 3.0.0
protocol: https
tags:
- description: Sample API
name: Sample Echo API
info:
title: UUID generator based on httpbin.org
version: 1.0.3
paths:
/uuid:
get:
responses:
"200":
description: A UUID4.
summary: Return a UUID4.
tags:
- UUID Ops
/uuid/{uuid}:
delete:
parameters:
- in: path
name: uuid
required: true
schema:
type: string
responses:
"200":
description: Deleted okay.
summary: This endpoint makes no sense.
tags:
- UUID Ops
- Experimental
/delay/{delay}:
get:
parameters:
- in: path
name: delay
required: true
schema:
type: integer
responses:
"200":
description: Returns a delayed response
summary: Returns a delayed response
tags:
- Delayed Response
- Experimental
servers:
- url: https://httpbin.org/
我想删除所有带有“实验”标签的 API 端点,所以基本上生成的文件是:
openapi: 3.0.0
protocol: https
tags:
- description: Sample API
name: Sample Echo API
info:
title: UUID generator based on httpbin.org
version: 1.0.3
paths:
/uuid:
get:
responses:
"200":
description: A UUID4.
summary: Return a UUID4.
tags:
- UUID Ops
servers:
- url: https://httpbin.org/
我苦苦挣扎的地方是为 yq
命令找到正确的 'level' 以这种方式工作。
例如,我知道我可以用几种不同的方式显示所有标签:
yq eval '.paths[]?[]?.tags?' openapi.yaml
或
yq eval '.. | select(. == "Experimental")' openapi.yaml
但是当我尝试如下操作时,根据标签删除父部分(即实际的 API 块):
yq eval '.paths | del(.. | select(. == "Experimental"))' openapi.yaml
或
yq eval '.paths |= with_entries(del(select(.. | select(. == "Experimental"))) )' openapi.yaml
它所做的只是删除特定的 Experimental
标签,而不是实际的 API 块。
请问我做错了什么?
对于 mikefarah/yq,这有点棘手,但您可以使用 with_entries
和 contains
方法来实现您想要的结果
yq e '
.paths |=
with_entries( select( .value[].tags | contains(["Experimental"] ) | not ) )' yaml
使用 with_entries,您的每个地图元素都被转换为 key/value 对,并且通过使用特殊符号 .value[]
,您可以绕过顶级键 - /uuid
, /uuid/{uuid}
并直接在 tags
使用 contains,我们能够仅过滤仅包含 "Experimental"
的必要对象,并使用 not
否定该条件以获得您想要的结果。