在变量名中调用其他变量(Bash)

lit*_*ice 7 bash shell-script variable-substitution variable

目前我有下一个路径

langs="EN GE"
dir_EN=/xx
dir_GE=/zz
Run Code Online (Sandbox Code Playgroud)

如您所见,变量 $langs 在单个数组中包含所有可能的语言。我想使用检查语言是什么的循环将所有这些路径保存在多语言(dir_ML)数组中,然后保存相应的路径。这是我到目前为止所拥有的

for i in $(seq 0 1); do #I used seq because I didn't know how to specify the length of the variable $langs
    dir_ML[$i]=dir_${langs[$i]}
done
Run Code Online (Sandbox Code Playgroud)

我正在寻找的输出是

dir_ML[0]=/xx

dir_ML[1]=/zz

我希望你能理解我在做什么!提前致谢

Kus*_*nda 10

langs 不是数组,而是代码中的字符串。

要使其成为数组并使用它:

langs=( EN GE )
dir_EN=/xx
dir_GE=/zz

dir_ml=()
for i in "${langs[@]}"; do
    declare -n p="dir_$i"
    dir_ml+=( "$p" )
done

printf 'dir_ml = "%s"\n' "${dir_ml[@]}"
Run Code Online (Sandbox Code Playgroud)

在上述循环中,$i将采取的值ENGE反过来。这也引入了名称引用变量p。当p访问 的值时,声明变量时分配给该变量的字符串将被解释为变量名,并且返回变量的值。

上面的输出将是

dir_ml = "/xx"
dir_ml = "/zz"
Run Code Online (Sandbox Code Playgroud)

要在 中使用名称引用bash,您需要bash4.3 或更高版本。


另一种(有趣但较差的)可能性:

dir_EN=/xx
dir_GE=/zz

# (can't set dir_ml=() here as its name would be picked up by the loop)
unset dir_ml

for i in "${!dir_@}"; do
    dir_ml+=( "${!i}" )
done

printf 'dir_ml = "%s"\n' "${dir_ml[@]}"
Run Code Online (Sandbox Code Playgroud)

这里,$i将采取的值的变量名 dir_ENdir_GE反过来。然后,我们使用变量间接${!i}获得该变量的值。这种变体不需要langs数组,而是假设没有其他变量被命名为dir_-something(这可能被认为有点脆弱,因为用户可以轻松地将具有此类名称的变量注入脚本环境)。

此代码的输出与上面的代码相同。


jes*_*e_b 6

这可以按如下方式完成:

#!/bin/bash
langs=(EN GE)
dir_EN=/xx
dir_GE=/zz

for i in ${!langs[@]}; do
        temp="dir_${langs[i]}"
        dir_ML[i]=${!temp}
done
Run Code Online (Sandbox Code Playgroud)

首先我改成langs="EN GE"langs=(EN GE)因为这需要是一个数组。

我还更改$(seq 0 1)${!langs[@]}which 将扩展为数组中每个项目的索引(或关联数组中的名称)。所以在这个例子中0 1

然后我将一个临时变量设置为dir_${langs[i]}(dir_ENdir_GE)。

然后使用!参数扩展我扩展具有该名称的变量以设置dir_ML