2017-04-12 67 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