使用变量将JSON直接存储在bash脚本中?

Ale*_*lex 11 bash json

我将在序言中说"不,找到一种不同的方式去做"这是一个可以接受的答案.

是否有一种可靠的方法可以在bash变量中存储一小段JSON,以便在从同一脚本运行的AWS CLI命令中使用?

我将从Jenkins运行一个正在更新AWS Route53记录的工作,该记录需要UPSERT一个带有记录更改的JSON文件.因为它是从Jenkins运行的,所以我没有本地存储可以保存这个文件,而且我真的很想避免每次运行这个项目时都需要进行git checkout(这将是每小时一次).

理想情况下,将数据存储在variable($foo)中并将其作为change-resource-record-sets命令的一部分进行调用将是最方便的,因为Jenkins设置,但我不熟悉如何在bash中引用/存储JSON - 它可以安全地完成吗?

在这种情况下,具体的JSON如下;

{"Comment":"Update DNSName.","Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"alex.","Type":"A","AliasTarget":{"HostedZoneId":"######","DNSName":"$bar","EvaluateTargetHealth":false}}}]}
Run Code Online (Sandbox Code Playgroud)

作为一个额外的复杂功能,DNSName值$bar- 需要扩展.

Ben*_* W. 35

你可以使用here-doc:

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

通过EOF在第一行中不加引号,here-doc的内容将受到参数扩展的影响,因此您可以$bar扩展到放在那里的任何内容.

如果您可以在JSON中使用换行符,则可以使其更具可读性:

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

或者甚至(每行的第一个缩进必须是制表符)

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

并显示如何存储,包括引用(假设bar=baz):

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

因为这会扩展shell元字符,如果你的JSON包含类似的内容,你可能会遇到麻烦`,所以或者你可以直接分配,但要注意引用$bar:

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

注意引用$bar:它是

"'"$bar"'"
???    ???
???    ??? literal double quote
???    ?? opening syntactical single quote
???    ? closing syntactical double quote
??? opening syntactical double quote
?? closing syntactical single quote
? literal double quote
Run Code Online (Sandbox Code Playgroud)

  • 这非常有效,特别感谢 bar 的引用细分,它解决了未来的问题! (2认同)

che*_*ner 9

它可以安全存放 ; 生成它是另一回事,因为$bar可能需要对内容进行编码.让像jqhandle 这样的工具创建JSON.

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

  • @Alex`jq`允许过滤器中的密钥不加引号(如果它是一个简单的字母数字键); 生成的JSON将有引号. (2认同)