2017-04-12 101 views
2

我會在前言中說「不,找到一個不同的方式來做到這一點」是一個可以接受的答案。將JSON直接存儲在帶有變量的bash腳本中?

是否有一種可靠的方法將短小的JSON存儲在bash變量中,以用於從相同腳本運行的AWS CLI命令?

我將從Jenkins運行一個更新AWS Route53記錄的作業,這需要UPSERT一個JSON文件並記錄更改。因爲它是從Jenkins運行的,所以沒有本地存儲可以保存該文件,並且我真的很想避免每次運行該項目時都需要執行git checkout(每小時一次)。

理想的情況下,將數據存儲在一個變量($foo),把它作爲change-resource-record-sets命令給出的詹金斯設置將是最方便的一部分,但我不熟悉如何正確地引用/存儲JSON中使用bash - 可以它安全地完成?

本例中具體的JSON如下;需要擴大 -

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

作爲一個額外的併發症DNSNAME值 - $bar

回答

9

你可以使用這裏-DOC:

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

通過在第一線未加引號離開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):

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

因爲t他的擴張shell元字符,你可能會遇到麻煩,如果你的JSON包含有類似*,所以或者,你可以直接分配,但要小心引述周圍$bar

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

通告$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,因此可以捕獲最終的錯誤,並確保生成的JSON始終正確。 (又名:使用正確的工具解決問題):) – jm666