合并 YAML 数组,忽略 YAML 中的其他字段
Merging YAML arrays, ignoring other fields in the YAML
我正在寻找一种方法来合并来自两个独立 YAML 的数组(将一个附加到另一个)。然而,YAML 有一个用 {}
包裹的字段(不在数组中),可以用运行时值替换。即
# yaml a
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
namespace: default
name: {clusterRoleName}
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
# yaml b
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
namespace: default
name: {clusterRoleName}
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "watch", "list"]
# desired
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
namespace: default
name: {clusterRoleName}
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "watch", "list"]
为此,我正在使用 yq 2.14 版。我试过 yq merge -a=append a.yaml b.yaml
,它按照我的意愿处理规则数组,但将 name: {clusterRoleName}
视为 JSON 并输出:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: {ClusterRoleName: ''}
...
有没有办法只合并一个字段,或者忽略特定的键或值类型?如果有人能够建议替代方法,我也不会为此使用 yq。
虽然使用专用的 yaml 解析器(例如 yq)是理想的选择,但使用 awk 可能是另一种选择:
awk 'NR==FNR && !/^[[:space:]]/ { tag=;next } tag=="rules:" && FNR==NR { map[idx++]=[=10=] } END { tag="" } NR!=FNR && !/^[[:space:]]/ { if (tag=="rules:") { for (i in map) { print map[i]}} tag= } NR!=FNR { print }' yamlb yamla
解释:
awk 'NR==FNR && !/^[[:space:]]/ { # Processing yamlb (NR==FNR) and there there are spaces at the beginning of the line
tag=; # Set the variable tag to the first space delimited field
next # Skip to the next file
}
tag=="rules:" && FNR==NR { # Process where tag is "rules:" and we are processing yamlb
map[idx++]=[=11=] # Put the line in an array map with in incrementing index
}
END {
tag="" # At the end of the file reset the variable tag
}
NR!=FNR && !/^[[:space:]]/ { # Process yamla where there are no spaces at the start of the line
if (tag=="rules:") {
for (i in map) {
print map[i] # If tag is equal to rules: print the array map
}
}
tag= # Set the variable tag to the first space delimited field.
}
NR!=FNR {
print # Print lines when we are processing yamla
}' yamlb yamla
我正在寻找一种方法来合并来自两个独立 YAML 的数组(将一个附加到另一个)。然而,YAML 有一个用 {}
包裹的字段(不在数组中),可以用运行时值替换。即
# yaml a
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
namespace: default
name: {clusterRoleName}
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
# yaml b
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
namespace: default
name: {clusterRoleName}
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "watch", "list"]
# desired
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
namespace: default
name: {clusterRoleName}
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "watch", "list"]
为此,我正在使用 yq 2.14 版。我试过 yq merge -a=append a.yaml b.yaml
,它按照我的意愿处理规则数组,但将 name: {clusterRoleName}
视为 JSON 并输出:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: {ClusterRoleName: ''}
...
有没有办法只合并一个字段,或者忽略特定的键或值类型?如果有人能够建议替代方法,我也不会为此使用 yq。
虽然使用专用的 yaml 解析器(例如 yq)是理想的选择,但使用 awk 可能是另一种选择:
awk 'NR==FNR && !/^[[:space:]]/ { tag=;next } tag=="rules:" && FNR==NR { map[idx++]=[=10=] } END { tag="" } NR!=FNR && !/^[[:space:]]/ { if (tag=="rules:") { for (i in map) { print map[i]}} tag= } NR!=FNR { print }' yamlb yamla
解释:
awk 'NR==FNR && !/^[[:space:]]/ { # Processing yamlb (NR==FNR) and there there are spaces at the beginning of the line
tag=; # Set the variable tag to the first space delimited field
next # Skip to the next file
}
tag=="rules:" && FNR==NR { # Process where tag is "rules:" and we are processing yamlb
map[idx++]=[=11=] # Put the line in an array map with in incrementing index
}
END {
tag="" # At the end of the file reset the variable tag
}
NR!=FNR && !/^[[:space:]]/ { # Process yamla where there are no spaces at the start of the line
if (tag=="rules:") {
for (i in map) {
print map[i] # If tag is equal to rules: print the array map
}
}
tag= # Set the variable tag to the first space delimited field.
}
NR!=FNR {
print # Print lines when we are processing yamla
}' yamlb yamla