![如何将单值参数从脚本传递到 JSON 文件而不覆盖现有值?](https://linux22.com/image/227224/%E5%A6%82%E4%BD%95%E5%B0%86%E5%8D%95%E5%80%BC%E5%8F%82%E6%95%B0%E4%BB%8E%E8%84%9A%E6%9C%AC%E4%BC%A0%E9%80%92%E5%88%B0%20JSON%20%E6%96%87%E4%BB%B6%E8%80%8C%E4%B8%8D%E8%A6%86%E7%9B%96%E7%8E%B0%E6%9C%89%E5%80%BC%EF%BC%9F.png)
我有以下名为的 JSON 文件pool.json
:
{
"AllocateActions": {},
"Available": true,
"Description": "Pool for nodes in cluster - {{CLUSTER_NAME}}",
"Endpoint": "",
"EnterActions": {
"AddProfiles": [
"{{RC_JOIN_PROFILE}}",
"image-deploy-profile",
"rc-controlplane-profile",
"rc-etcd-profile"
],
"Workflow": "rc-image-deploy"
},
"Errors": [],
"ExitActions": {
"RemoveProfiles": [
"{{RC_JOIN_PROFILE}}",
"image-deploy-profile"
],
"Workflow": "discover-base"
},
"Meta": {
"color": "black",
"feature-flags": "sane-exit-codes",
"icon": "object ungroup outline",
"title": "User added"
},
"ReadOnly": true,
"ReleaseActions": {},
"Validated": true
}
在我的 bash 脚本中,我用来jq
将值传递给这些 JSON 占位符:
NODE_JSON=$(jq --arg RC_JOIN_PROFILE "$RC_JOIN_PROFILE" --arg CLUSTER_NAME "$CLUSTER_NAME" '.Description = "'$CLUSTER_NAME'"| .ExitActions.RemoveProfiles = [ "'$RC_JOIN_PROFILE'" ] | .EnterActions.AddProfiles = [ "'$RC_JOIN_PROFILE'" ]' pool.json)
如果我传递RC_JOIN_PROFILE="test-profile"
和CLUSTER_NAME="test-cluster"
,那么我期望最终的 JSON 如下:
{
"AllocateActions": {},
"Available": true,
"Description": "Pool for nodes in cluster - test-cluster",
"Endpoint": "",
"EnterActions": {
"AddProfiles": [
"test-profile",
"image-deploy-profile",
"rc-controlplane-profile",
"rc-etcd-profile"
],
"Workflow": "rc-image-deploy"
},
"Errors": [],
"ExitActions": {
"RemoveProfiles": [
"test-profile",
"image-deploy-profile"
],
"Workflow": "discover-base"
},
"Meta": {
"color": "black",
"feature-flags": "sane-exit-codes",
"icon": "object ungroup outline",
"title": "User added"
},
"ReadOnly": true,
"ReleaseActions": {},
"Validated": true
}
但是,我在下面得到了 JSON:
{
"AllocateActions": {},
"Available": true,
"Description": "test-cluster",
"Endpoint": "",
"EnterActions": {
"AddProfiles": [
"test-profile",
],
"Workflow": "rc-image-deploy"
},
"Errors": [],
"ExitActions": {
"RemoveProfiles": [
"test-profile",
],
"Workflow": "discover-base"
},
"Meta": {
"color": "black",
"feature-flags": "sane-exit-codes",
"icon": "object ungroup outline",
"title": "User added"
},
"ReadOnly": true,
"ReleaseActions": {},
"Validated": true
}
.ExitActions.AddPofiles
、.ExitActions.RemoveProfiles
和的现有值.Description
已被传递的值覆盖。我想要带有传递值的现有值。我尝试了很多场景,但没有任何效果。谁能帮我这个?
答案1
您的代码存在三个主要问题:
- 您定义了
jq
从未使用过的变量。 - 你放将数组更改为值而不是更新它们。
- 您不会尝试匹配模板占位符。
相反,将值传递给内部jq
变量,使用sub()
适当的值替换模板占位符,使用|=
运算符来简化更新必要的数据(a |= expression
与 相同a = (a | expression)
)。
jq --arg clustername "$CLUSTER_NAME" --arg profilename "$RC_JOIN_PROFILE" '
.Description |= sub("{{CLUSTER_NAME}}"; $clustername) |
.EnterActions.AddProfiles |= map(sub("{{RC_JOIN_PROFILE}}"; $profilename)) |
.ExitActions.RemoveProfiles |= map(sub("{{RC_JOIN_PROFILE}}"; $profilename))' pool.json
此处,输入 JSON 中具有模板占位符的三位将被更新,以sub()
将占位符替换为适当的值。这两个数组是通过将调用映射sub()
到它们的每个元素来处理的,这样我们就不必依赖占位符在数组中的位置。
如果您只想影响数组的第一个元素,请使用例如
.ExitActions.RemoveProfiles[0] |= sub("{{RC_JOIN_PROFILE}}"; $profilename)
或者,如果你只是想分配数组第一个元素的值,
.ExitActions.RemoveProfiles[0] = $profilename
(对于第一个数组也类似,但不使用map()
)。
对给定数据运行的示例:
$ CLUSTER_NAME='Test Cluster Name "Charlie"'
$ RC_JOIN_PROFILE='Test RC Join Profile "Matilda"'
$ jq --arg clustername "$CLUSTER_NAME" --arg profilename "$RC_JOIN_PROFILE" '.Description |= sub("{{CLUSTER_NAME}}"; $clustername) | .EnterActions.AddProfiles |= map(sub("{{RC_JOIN_PROFILE}}"; $profilename)) | .ExitActions.RemoveProfiles |= map(sub("{{RC_JOIN_PROFILE}}"; $profilename))' pool.json
{
"AllocateActions": {},
"Available": true,
"Description": "Pool for nodes in cluster - Test Cluster Name \"Charlie\"",
"Endpoint": "",
"EnterActions": {
"AddProfiles": [
"Test RC Join Profile \"Matilda\"",
"image-deploy-profile",
"rc-controlplane-profile",
"rc-etcd-profile"
],
"Workflow": "rc-image-deploy"
},
"Errors": [],
"ExitActions": {
"RemoveProfiles": [
"Test RC Join Profile \"Matilda\"",
"image-deploy-profile"
],
"Workflow": "discover-base"
},
"Meta": {
"color": "black",
"feature-flags": "sane-exit-codes",
"icon": "object ungroup outline",
"title": "User added"
},
"ReadOnly": true,
"ReleaseActions": {},
"Validated": true
}
请注意,通过使用在命令行上定义的jq
变量clustername
和,我们可以正确处理字符串的引用。profilename
--arg
jq