如何将单值参数从脚本传递到 JSON 文件而不覆盖现有值?

如何将单值参数从脚本传递到 JSON 文件而不覆盖现有值?

我有以下名为的 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

您的代码存在三个主要问题:

  1. 您定义了jq从未使用过的变量。
  2. 将数组更改为值而不是更新它们。
  3. 您不会尝试匹配模板占位符。

相反,将值传递给内部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--argjq

相关内容