如何在Bash中将动态值存储为数组变量?
解决方案:正确将Azure Key Vault秘密数据存储为Bash数组
问题根源
当前脚本中getapp和getserviceprincipal被赋值为命令输出的字符串而非数组,Bash不会自动将多行输出拆分为数组元素;同时两次调用az keyvault secret list可能因数据更新导致两组结果不匹配,循环条件也存在语法错误。
修改后的完整脚本
#!/bin/bash ExpirationDate=$(date -d '+60 days' +'%Y-%m-%d') VaultName="abc" # 一次API调用获取所有需要的字段,用jq按"SecretName|Type"格式输出每行 readarray -t secrets < <(az keyvault secret list --vault-name "$VaultName" \ --query "[?attributes.expires<='$ExpirationDate'].{SecretName:name, Type:contentType}" \ | jq -r '.[] | "\(.SecretName)|\(.Type)"') # 初始化目标数组 declare -a getapp=() declare -a getserviceprincipal=() # 拆分每行数据到对应数组 for secret in "${secrets[@]}"; do IFS='|' read -r app sp <<< "$secret" getapp+=("$app") getserviceprincipal+=("$sp") done # 遍历数组执行操作 for ((i=0; i<${#getapp[@]}; i++)); do echo "${getapp[$i]}" ./resetpassword.sh -a "${getapp[$i]}" -s "${getserviceprincipal[$i]}" -y echo "${getserviceprincipal[$i]}" done
关键优化点
单次API调用
避免两次调用az命令,防止两次请求之间秘密状态变化导致数据不匹配,同时减少API开销。通过jq将每个秘密的名称和类型用|拼接成单行,确保数据一一对应。正确读取数组
使用readarray -t secrets将命令输出的每行内容直接转为数组元素,-t参数自动去除每行末尾的换行符。安全拆分数据
通过IFS='|'指定分隔符,将每行内容拆分为秘密名称和类型,分别存入目标数组,避免空格等特殊字符导致的拆分错误。修正循环逻辑
用i<${#getapp[@]}作为循环条件,确保遍历所有数组元素,替换原脚本中i-le$len-1的语法错误。
备选方案(直接转数组)
如果坚持分两次调用API,可通过以下方式将输出直接转为数组:
# 将getapp转为数组,IFS设为换行避免空格拆分元素 IFS=$'\n' read -r -d '' -a getapp < <(az keyvault secret list --vault-name "$VaultName" \ --query "[?attributes.expires<='$ExpirationDate'].name" | jq -r '.[]') # 同理处理getserviceprincipal IFS=$'\n' read -r -d '' -a getserviceprincipal < <(az keyvault secret list --vault-name "$VaultName" \ --query "[?attributes.expires<='$ExpirationDate'].contentType" | jq -r '.[]')
注:此方案仍存在两次API调用导致数据不一致的风险,优先推荐单次调用的方案。
内容的提问来源于stack exchange,提问作者bashiefy
相关产品推荐
相关产品推荐

