2017-04-12 1 views
2

필자는 "아니, 할 다른 방법을 찾아라"는 말로 머리말을 붙일 것입니다.JSON을 변수가있는 bash 스크립트에 직접 저장 하시겠습니까?

동일한 스크립트에서 실행되는 AWS CLI 명령에 사용할 JSON의 짧은 비트를 bash 변수에 저장할 수있는 확실한 방법이 있습니까?

저는 Jenkins에서 AWS Route53 레코드를 업데이트하고 있습니다. 레코드 변경으로 JSON 파일을 UPSERT해야합니다. Jenkins에서 실행 중이므로이 파일을 저장할 수있는 로컬 저장소가 없으므로이 프로젝트가 실행될 때마다 (한 시간에 한 번씩) git checkout을 수행하지 않아도됩니다.

이상적으로, 변수 ($foo)에 데이터를 저장하고 젠킨스 설정 주어진 가장 편리 할 것 change-resource-record-sets 명령의 일부로 호출,하지만 난/저장 JSON 내부 떠들썩한 파티를 인용하는 방법을 정확하게에 익숙 해요 - 수 안전하게 할 수 있니?

이 경우의 특정 JSON은 다음과 같습니다. $bar - - 추가 합병증 DNSName 값으로

{"Comment":"Update DNSName.","Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"alex.","Type":"A","AliasTarget":{"HostedZoneId":"######","DNSName":"$bar","EvaluateTargetHealth":false}}}]} 

확장 될 필요가있다.

당신은 여기-문서 사용할 수

답변

9

: 인용 부호로 둘러싸이지 않은 첫 번째 줄에 EOF두면

foo=$(cat <<EOF 
{"Comment":"Update DNSName.","Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"alex.","Type":"A","AliasTarget":{"HostedZoneId":"######","DNSName":"$bar","EvaluateTargetHealth":false}}}]} 
EOF 
) 

는 여기-문서의 내용이 있으므로 $bar 당신이 넣어 어떤로 확장, 매개 변수 확장이 적용됩니다 거기에.

당신이 당신의 JSON에서 줄 바꿈을 가질 수 있다면, 당신이 좀 더 읽기 쉽게 만들 수 있습니다 심지어

foo=$(cat <<EOF 
{ 
    "Comment": "Update DNSName.", 
    "Changes": [ 
    { 
     "Action": "UPSERT", 
     "ResourceRecordSet": { 
     "Name": "alex.", 
     "Type": "A", 
     "AliasTarget": { 
      "HostedZoneId": "######", 
      "DNSName": "$bar", 
      "EvaluateTargetHealth": false 
     } 
     } 
    } 
    ] 
} 
EOF 
) 

또는 (각 행의 첫 번째 들여 쓰기 탭이어야 함)

foo=$(cat <<-EOF 
    { 
     "Comment": "Update DNSName.", 
     "Changes": [ 
     { 
      "Action": "UPSERT", 
      "ResourceRecordSet": { 
      "Name": "alex.", 
      "Type": "A", 
      "AliasTarget": { 
       "HostedZoneId": "######", 
       "DNSName": "baz", 
       "EvaluateTargetHealth": false 
      } 
      } 
     } 
     ] 
    } 
    EOF 
) 

및 그 인용이 포함 저장되는 방법을 표시한다 (즉 가정 bar=baz) t 때문에

$ declare -p foo 
declare -- foo="{ 
    \"Comment\": \"Update DNSName.\", 
    \"Changes\": [ 
    { 
     \"Action\": \"UPSERT\", 
     \"ResourceRecordSet\": { 
     \"Name\": \"alex.\", 
     \"Type\": \"A\", 
     \"AliasTarget\": { 
      \"HostedZoneId\": \"######\", 
      \"DNSName\": \"baz\", 
      \"EvaluateTargetHealth\": false 
     } 
     } 
    } 
    ] 
}" 

foo='{"Comment":"Update DNSName.","Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"alex.","Type":"A","AliasTarget":{"HostedZoneId":"######","DNSName":"'"$bar"'","EvaluateTargetHealth":false}}}]}' 

주의가 $bar에 대한 인용 : 자신의 팽창은 당신이 당신의 JSON 그래서 대안 * 같은 포함 된 경우 직접 지정할 수, 문제로 실행되지만 $bar 주위에 인용에 대해주의 수, 메타 문자 쉘은

있어
"'"$bar"'" 
^^^ ^^^ 
||| ||| 
||| ||literal double quote 
||| |opening syntactical single quote 
||| closing syntactical double quote 
||opening syntactical double quote 
|closing syntactical single quote 
literal double quote 
+0

이것은 완벽하게 작동했습니다. 특히 바에 대한 인용문을 작성해 주셔서 감사합니다. – Alex

6

으로 안전하게 저장할 수 있습니다. 을 생성하면 $bar의 내용을 인코딩해야 할 수 있으므로 다른 문제입니다. jq과 같은 도구를 사용하여 JSON을 생성합니다.

var=$(jq -n --arg b "$bar" '{ 
    Comment: "Update DNSName.", 
    Changes: [ 
    { 
     Action: "UPSERT", 
     ResourceRecordSet: { 
     Name: "alex.", 
     Type: "A", 
     AliasTarget: { 
      HostedZoneId: "######", 
      DNSName: $b, 
      EvaluateTargetHealth: false 
     } 
     } 
    } 
    ] 
}') 
+0

jq는 다른 곳에서 사용하는 것처럼 절대적으로 옵션이지만 따옴표의 부족에 대해 궁금합니다 - jq가 모든 것을 둘러싼 따옴표를 처리하거나 예를 들어서 제외시킨 것입니까? AWS는 인용 된 키 쌍을 요구하는 것 같습니다. – Alex

+2

@Alex'jq'는 단순히 문자 숫자 식 키인 경우 필터의 키를 따옴표로 묶을 수 없도록합니다. 생성 된 JSON에는 따옴표가 붙습니다. – chepner

+0

이것은 ** 해결책입니다. 왜냐하면'jq'가 JSON을 검사하여 가능한 최종 결과 오류를 catch하고 생성 된 JSON이 항상 올바른지 확인하기 때문입니다. (일명 : 문제에 대한 올바른 도구 사용) :) – jm666

관련 문제