我正在尝试使用 json 将变量拉入循环

Im trying to use json to pull a variable into a loop

我正在复制json?从两个网站尝试实现我的目标

https://softwaredevelopmentstuff.com/2017/05/02/downloading-an-aws-glacier-archive-step-by-step/

https://gist.github.com/veuncent/ac21ae8131f24d3971a621fac0d95be5

这个有效:

#!/bin/bash

file='/home/nat/Documents/glacier_access/output.json'

if [[ -z ${AWS_ACCOUNT_ID} ]] || [[ -z ${AWS_REGION} ]] || [[ -z ${AWS_VAULT_NAME} ]]; then
    echo "Please set the following environment variables: "
    echo "AWS_ACCOUNT_ID"
    echo "AWS_REGION"
    echo "AWS_VAULT_NAME"
    exit 1
fi

archive_ids=$(jq .ArchiveList[].ArchiveId < $file)

for archive_id in ${archive_ids}; do
    echo "Downloading Archive: ${archive_id}"
     aws glacier delete-archive --archive-id=${archive_id} --vault-name ${AWS_VAULT_NAME} --account-id ${AWS_ACCOUNT_ID} --region ${AWS_REGION}
 
done

就像这样:

# file to loop action on archives
#!/bin/bash

file='/home/nat/Documents/glacier_access/output.json'

if [[ -z ${AWS_ACCOUNT_ID} ]] || [[ -z ${AWS_REGION} ]] || [[ -z ${AWS_VAULT_NAME} ]]; then
    echo "Please set the following environment variables: "
    echo "AWS_ACCOUNT_ID"
    echo "AWS_REGION"
    echo "AWS_VAULT_NAME"
    exit 1
fi

archive_ids=$(jq .ArchiveList[].ArchiveId < $file)

for archive_id in ${archive_ids}; do
    echo "Downloading Archive: ${archive_id}"
aws glacier initiate-job \
    --account-id 510422384120\
    --vault-name ebony-backup \
    --job-parameters '{
        "Type": "archive-retrieval",
        "Description": "Download all my archives",
        "ArchiveId": "w0GUthLDLDR6NL1z4c53M1IFktxBCrW_qZ2Qm_",
    }'
 
done

但是我不能在循环中引用变量

所以这不起作用:

"ArchiveId": "${archive_id}"

也不是这个:

"ArchiveId": "{archive_id}"

需要注意的重要一点是必须从作业参数部分引用 ArcihiveID。

感谢收到的任何帮助。我假设这是一个 JSON 问题?

您关于不能在循环中使用变量的说法是错误的。您已经使用 echo "Downloading Archive: ${archive_id}" 证明了这一点。这意味着问题实际上出在循环的第二个命令上。

具体来说,问题在于您构建用作 --job-parameters 参数的字符串。单引号中的所有内容都是准确生成的,因此您生成了字符串

{
        "Type": "archive-retrieval",
        "Description": "Download all my archives",
        "ArchiveId": "${archive_id}"
    }

接下来有四种解决方案。


使用双引号字符串从 shell 创建 JSON

    --job-parameters "{
        \"Type\":        \"archive-retrieval\",
        \"Description\": \"Download all my archives\",
        \"ArchiveId\":   \"$archive_id\"
    }"

总的来说,我讨厌从 shell 脚本生成代码的方法。然而,在这种情况下它是安全的,因为 id 完全由单词字符组成。不过,我们确实以很多反斜杠结尾。

使用 here-doc

从 shell 创建 JSON
    --job-parameters <<EOS
{
   "Type":        "archive-retrieval",
   "Description": "Download all my archives",
   "ArchiveId":   "$archive_id"
}
EOS

这仍在从 shell 脚本生成代码。但是通过使用 here-doc," 不再特殊,因此无需转义它们。

使用 jq

创建 JSON
    --job-parameters "$(
       jq -n --arg archive_id "$archive_id" '
          {
             "Type":        "archive-retrieval",
             "Description": "Download all my archives",
             "ArchiveId":   $archive_id
          }
       '
    )"

请注意,这在 jq 程序中使用了 jq 变量 $archive_id(使用 --arg 创建),因此没有引号。 jq 将为它生成正确的 JSON 字符串文字(如果包含特殊字符,如 ",则包括它)。

这更简洁,即使 archive_id 包含特殊字符也能正常工作。有点慢,每次都要启动jq

使用 jq 的单个实例创建 JSON

这解决了必须多次启动 jq 的问题。

jq -c '
   .ArchiveList[] |
   {
      "Type":        "archive-retrieval",
      "Description": "Download all my archives",
      "ArchiveId":   .ArchiveId
   }
' "$file" |
while read -r job; do
   aws glacier initiate-job     \
      --account-id 510422384120 \
      --vault-name ebony-backup \
      --job-parameters "$job"
done

请注意,存档 ID 后不应有逗号。 JSON.

中不允许尾随逗号