기존 값을 덮어쓰지 않고 스크립트에서 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
 }

jq내 Bash 스크립트에서는 다음 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

관련 정보