Reputation: 51
This works:
echo ${!var_pointing_to_another_var}
This doesn't:
echo ${!${var}_string_suffix}
In other words, I have a variable consisting of two parts: the first part is another variable, the second part is a string suffix. Together, they form a variable that would point to another variable. But I get a bad substitution error.
Due to readability and security issues, I want to avoid the eval
command.
Upvotes: 5
Views: 1919
Reputation: 12442
As far as I know, this is the only way:
t="${var}_string_suffix"
echo "${!t}"
Upvotes: 4
Reputation: 6627
http://mywiki.wooledge.org/BashFAQ/006
What you probably want is an associative array.
# The most common multi-dimensional array emulation for bash >= 4.0 is
# to use an associative array with delimiter.
typeset -A arr=([foo;bar]=test)
printf '%s\n' "${arr[$(printf '%q;%q' "$var1" "$var2")]}" # bash 4
Indirection using ${!var}
is less portable and not necessarily safer than eval
. eval
based indirection is well-understood, while bash indirect expansion can introduce obscure bugs without a solid understanding of its mechanics and careful input validation. The above wiki page provides a good introduction. "namerefs" are another workaround for bash 4.3, but they generally shouldn't be used in this way.
var1=foo
var2=bar
foobar=test
ref=${var1}${var2}
printf '%s\n' "${!ref}" # print test (bash-only, <= 4.3)
# Note: not a great example of nameref usage
typeset -n ref2=${var1}${var2}
printf '%s\n' "$ref2" # bash >= 4.3 / ksh93 / mksh
# Correct eval usage
if [[ $ref == [a-zA-Z_]+([a-zA-Z0-9_]) ]]; then
eval printf '%s\\n' "\${$ref}" # POSIX
eval printf '%s\\n' "$(printf '${%q}' "$ref")" # bash / ksh93 / zsh
fi
Upvotes: 2