Reputation: 3651
A lot of similar questions, but hadn't found one for using a variable in the name this way:
#!/bin/bash
# $1 should be 'dev' or 'stg'
dev_path="/path/to/123"
stg_path="/path/to/xyz"
# Use $1 as input to determine which path variable to 'execute'
${!\$1'/morepath'}
Using $1, I want to be able to reference either $dev_path or $stg_path ($1 == 'dev' or $1 == 'stg') and be able to reference the value of $1_path which would be '/path/to/123' or '/path/to/xyz'
so the result would either be:
'/path/to/123/morepath' or '/path/to/xyz/morepath'
based upon $1 being 'dev' or 'stg'.
I've tried various iterations of using ! and \$ in various places from other posts, but no luck
Upvotes: 1
Views: 583
Reputation: 75568
I think that would be unsafe. If $1
gets a value that's not dev or stg it would cause syntax error and other unexpected things may happen. Even with eval
it wouldn't be a good idea unless you add a conditional filter. You could use a case
statement:
case "$1" in
dev)
"$dev_path"/bin/execute
;;
std)
"$std_path"/bin/execute
;;
*)
echo "Invalid argument: $1"
;;
esac
Or make sure it's valid and use eval:
[[ $1 == dev || $1 == std ]] && eval "\"\${${1}_path}/bin/execute\""
Using if ... elif ...
could be valid too but the case
method is simpler.
As for variable indirection
you would need to store "${1}_path"
to another variable first which is unnecessary.
You could also use dev|std) eval ... ;;
in the case
statement at your preference.
Upvotes: 3
Reputation: 400512
See the Bash manual section on shell parameter expansion:
If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as
indirect expansion
. The exceptions to this are the expansions of${!prefix }
and${!name[@]}
described below. The exclamation point must immediately follow the left brace in order to introduce indirection.[...]
Since you also want to modify the name (by suffixing _path
) before expanding again, you need to go through another variable:
# $1 should be 'dev' or 'stg'
dev_path="/path/to/dev"
stg_path="/path/to/stg"
path=${1}_path # path is now either 'dev_path' or 'stg_path'
# Run either /path/to/dev or /path/to/stg
${!path}/bin/execute
Of course, if both of the dev
and stg
programs are in the same directory, then there's no need for all this, you can just directly expand $1
:
/path/to/$1/bin/execute
Upvotes: 6
Reputation: 19319
Why the need for a "variable, variable"? Why not
MYPATH="/path/to/$1"
$MYPATH/bin/execute
Upvotes: 0