bash 可以在字符串上使用间接扩展而不是构造临时变量吗?

bash 可以在字符串上使用间接扩展而不是构造临时变量吗?

假设我们都读过https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html(具体来说,搜索间接扩张)。

这个问题的意思是,而不是这样做:

alpha_date=1563980822; alpha_hash=bfc1a9ad; alpha_url=http://example.com/bfc1a9ad; alpha_path=/build/alpha; alpha_status=failure; bravo_date=1563981822; bravo_hash=f76025c5; bravo_url=http://example.com/f76025c5; bravo_path=/build/alpha2; bravo_status=success; charlie_date=1563982822; charlie_hash=289f55fd; charlie_url=http://example.com/289f55fd; charlie_path=/build/charlie; charlie_status=success

for prefix in alpha bravo charlie; do
    for suffix in date hash url path status; do
        tempvar="${prefix}_${suffix}"
        echo -n "$tempvar: ${!tempvar}"$'\t'
    done
    echo
done

这有效并输出:

alpha_date: 1563980822      alpha_hash: bfc1a9ad      alpha_url: http://example.com/bfc1a9ad      alpha_path: /build/alpha        alpha_status: failure
bravo_date: 1563981822      bravo_hash: f76025c5      bravo_url: http://example.com/f76025c5      bravo_path: /build/alpha2       bravo_status: success
charlie_date: 1563982822    charlie_hash: 289f55fd    charlie_url: http://example.com/289f55fd    charlie_path: /build/charlie    charlie_status: success

我想跳过创建tempvar这样的东西:

for prefix in alpha bravo charlie; do
    for suffix in date hash url path status; do
        echo -n "${prefix}_${suffix} is ${!${prefix}_${suffix}}"$'\t'
    done
    echo
done

但当然我bad substitution从 bash 中得到了一个错误。

有什么办法可以进行 bash“间接扩张”在“绳子”上?

答案1

如果您想设置变量,有很多方法(read "$a$b"printf -v "$a$b" ...declare "$a$b"=...等)。

如果要读取该值,如果最终值为数字,则可以使用算术扩展来完成,因为算术扩展可以嵌套(但也请参阅在 Shell 算术评估中使用未经净化的数据的安全影响):

$ a=a b=cd acd=10
$ echo $(($a$b))
10

一般来说,bash 不支持嵌套替换。

当然,您的玩具示例可以在某种程度上被模仿:

for prefix in alpha bravo charlie; do
    for suffix in date hash url path status; do
        declare -p "${prefix}_${suffix}"
    done
done

或者你可以尝试一下eval

eval "echo \"${prefix}_${suffix} is \${${prefix}_${suffix}}\""

答案2

您可以使用brace expansion构建变量名称:

for i in {alpha,bravo,charlie}_{date,hash,url,path,status}; do
  echo "$i is ${!i}"
done

答案3

如果使用ksh93相反,你可以这样做:

data=(
  [alpha]=(
    [date]=1563980822
    [hash]=bfc1a9ad
    [url]=http://example.com/bfc1a9ad
    [path]=/build/alpha
    [status]=failure
  )
  [bravo]=(
    [date]=1563981822
    [hash]=f76025c5
    [url]=http://example.com/f76025c5
    [path]=/build/alpha2
    [status]=success
  )
  [charlie]=(
    [date]=1563982822
    [hash]=289f55fd
    [url]=http://example.com/289f55fd
    [path]=/build/charlie
    [status]=success
  )
)
for prefix in alpha bravo charlie; do
    for suffix in date hash url path status; do
        printf '%s\n' "$prefix, $suffix, ${data[$prefix][$suffix]}"
    done
done

相关内容