Bash - Add variable in associative array - bad substitution [duplicate] - bash

This question already has answers here:
Bash indirect variable referencing
(1 answer)
Bash indirect array addressing?
(3 answers)
Closed 2 years ago.
Here is an expected behavior for associated array in bash
$ declare -A PC=( [Monitor]=Dell [CPU]=HP )
$ echo ${PC[CPU]}
HP
This gives me HP as output
Lets say I have these PC,Monitor amd CPU values stored in variable a , b and c. I am trying fetch the details now but I am getting "bad substitution" error when trying so.
$ a=PC; b=Dell; c=HP
$ echo ${$a[$b]}
bash: ${$a[$b]}: bad substitution
$ echo ${PC[$b]}
Dell
${PC[$b]} however is returning expected output but not {$a[$b]}
Not sure how this can be achieved. Thanks in advance.

What you are trying to do is called indirection - using one variable as the name of another variable.
In bash you do this for normal variables using the syntax ${!var}, as in
a=5
b=a
echo ${!b} # 5
Unfortunately this won't work how you want for an array variable because the syntax ${!array[*]} means something else (getting all keys from an associative array).
Instead, as suggested by a comment below, you can create a string for the entire reference and then use redirection on that:
lookup="$a[$b]"
echo ${!lookup} # will give Dell in your example

Related

Combine two variables to form the identifier for another variable in Bash [duplicate]

This question already has answers here:
How to get a variable value if variable name is stored as string?
(10 answers)
Closed 1 year ago.
I want to be able to take the values of two variables and concatenate them together to form the identifier for another variable in a bash script.
final_answer="we did it"
one="final"
two="answer"
t="${one}_${two}"
echo ${$t} # would like this to echo we did it; currently give "${$t}: bad substitution"
Not sure this is possible but it seems like bash would have this capacity somehow.
Thank you!
$ echo "${!t}"
we did it
See http://mywiki.wooledge.org/BashFAQ/006#Indirection for details.

how to recall variables from array in bash [duplicate]

This question already has answers here:
How to use a variable's value as another variable's name in bash [duplicate]
(6 answers)
Closed 3 years ago.
I have the following system variables:
$var01="this is var01"
$var02="this is var02"
$var03="this is var03"
$Var04="this is var04"
I want to use a for loop to recall each of them:
for i in {0..4}
do
echo "content of var$i is: $[var$i]"
done
but the above for loop gives me an error saying "bad substitution".
How should I construct echo parameter so to get the following result:
content of var01 is: this is var01
content of var02 is: this is var02
content of var03 is: this is var03
content of var04 is: this is var04
I suggest with bash >= 4.3:
for i in {0..4}; do x="var$i"; echo "${!x}"; done
See: Nameref

how to use variable variable names in bash script [duplicate]

This question already has answers here:
How to use a variable's value as another variable's name in bash [duplicate]
(6 answers)
Closed 6 years ago.
I'm trying to get the values of some php variables into a bash script in order to set other bash variables. Basically I need to be able to access the value of a variable - variable name.
the script can find & read the file, find the php variables, but when I try to set them it just hangs. Here is what I have:
variables=(database_user database_password dbase);
paths=(modx_core_path modx_connectors_path modx_manager_path modx_base_path);
for index in "${variables[#]}"; do
index=\$$index
echo $index;
$index="$(grep -oE '\$${!index} = .*;' $config | tail -1 | sed 's/$${!index} = //g;s/;//g')";
done
not sure what I am doing wrong here...
You are trying to perform an indirect assignment.
You should get rid of these two lines :
index=\$$index
echo $index;
By simply writing :
echo "${!index}"
Which does an indirect expansion cleanly (gives you the value of the variable whose name is contained in variable index).
Next, the problematic line is this one:
$index="$(grep -oE '\$${!index} = .*;' ... (rest omitted)
In Bash, an assignment cannot begin with a $.
One way you can perform an indirect assignment is this (after removing the index re-assignment as suggested above) :
printf -v "$index" "$(grep -oE '\$${!index} = .*;' ... (rest omitted)
This uses the -v option of printf, which causes the value passed as the final argument to be assigned to a variable, the name of which is passed to the -v option.
There are other ways of handling indirect assignment/expansions, some with code injection risks, as they use (potentially uncontrolled) data as code. This is something you may want to research further.
Please note I am assuming the actual grep command substitution works (I have not tested).

Can I set a value to a variable via alias of it in bash? [duplicate]

This question already has answers here:
Indirect variable assignment in bash
(7 answers)
Closed 6 years ago.
I would like to set a value via alias of it in bash, like following.
ORIGINAL_VALUE="a"
ALIAS="ORIGINAL_VALUE"
"$ALIAS"="b" # This line does not work.
echo "value is $ORIGINAL_VALUE"
The result I expect is
value is b
Now I know it is possible to read the value of ORIGINAL_VALUE via ALIAS by
${!ALIAS}
But, unfortunately, I don't know how to set the value of ORIGINAL_VALUE via ALIAS, like "$ALIAS"="b", which does not work.
Some who has a solution or a suggestion, please tell me it.
Thank you very much.
Use a nameref (bash 4.3 or later)
$ declare -n alias=original_value
$ original_value=a
$ alias=b
$ echo "$original_value"
b
You can use declare:
ORIGINAL_VALUE="a"
ALIAS="ORIGINAL_VALUE"
declare $ALIAS="b"
echo "value is $ORIGINAL_VALUE"
Output:
value is b
Side note: If you put this into a function and want to change the value of a variable from outside the scope of the function this won't work since declare would redeclare the variable locally in that case.
Assuming you can trust the variables are safe:
eval $ALIAS=b

Unable to print value of shell variable stored in another variable [duplicate]

This question already has answers here:
Lookup variable value from string in shell script
(2 answers)
Closed 8 years ago.
I'm trying to find all variables which match a particular pattern and print their values.
test_a="apple"
test_b="banana"
test_c="carrot"
test_d="doughnut"
test_show_all () {
local i
for i in ${!test_*}; do
printf "..$i\n"
# printf "..$i-->${$i}\n"
done
}
The loop is finding the correct variables.
But if I uncomment the second line of the for loop, bash is unhappy with the syntax ${$i}. I thought this should work since $i holds the name of a variable, so I thought ${$i} should expand to value of that stored name.
The indirect variable reference is ${!var}. Change your code to
printf "..$i-->${!i}\n"
and it should work.
Not useful now, but in bash 4.3, you will also be able to use namerefs.
for name in ${!test_*}; do
declare -n value=$name
printf "..$name->$value\n"
done
As a short cut, if you only want to iterate over the values (without regard to the actual name of the variable), you can use
declare -n value
for value in ${!test_*}; do
printf "..$value\n"
done

Resources