Getting value of environment variable in unix - bash

I have a properties file to set some environment variables say:
mydata.properties:
VAR1=Data1
VAR2=Data2
Now I want to define a new variable called VAR3 that can hold either VAR1 or VAR2 like:
mydata.properties:
VAR1=Data1
VAR2=Data2
VAR3=VAR2
To make these variables to be available to my bash session I am using this command
source mydata.properties
Now my requirement is to print the value for VAR3 so that it can print the internal data of the sourced VAR2 variable like:
Value of VAR3 is Data2
I tried different options like
echo "Value of VAR3 is $$VAR3"
This gives me junk output.
or echo "Value of VAR3 is ${$VAR3}"
This give me error as Value of ${$VAR3}: bad substitution
Please help me how to get this output.

If you really need to expand the variable that VAR3 points to (instead of just setting VAR3 to the value of VAR2 to begin with), you can use indirect variable expansion with ${!varname}:
$ VAR1=Data1
$ VAR2=Data2
$ VAR3=VAR2
$ echo "${!VAR3}"
Data2

I don't use bash, but
mydata.properties:
VAR1=Data1
VAR2=Data2
VAR3=$VAR2
should do it. Note the extra $ infront of var2 in the last line.

You might want to get into the habit of doing it this way:
VAR3=${VAR2}
This is the same as VAR3=$VAR2, but when you are using variables embedded in other text (like VAR3=${VAR2}_foo), you will need the {}, so it's a good idea to use them by default.

You want
VAR2=$VAR3
then
echo "Value of VAR3 is $VAR3"
Note the single $ in both places. You use the $ to reference the value of variables, so you need to use it when assigning the value of VAR2, and when printing its value in the echo command

I think you want to know how to make a reference in BASH. The syntax can be rather tricky. It involves using eval and echo to be able to set the value:
VAR2=Data2
VAR3=VAR2 #Reference!
echo "The value of $VAR3 is $(eval echo \$$VAR3)"
It's better to use hash arrays instead of trying to use references directly:
REF[VAR3]=$VAR2
echo "The value of VAR3 = ${REF[VAR3]}"
Or, as others point out, you could have simply done this:
VAR3="$VAR2"
if you merely want to set $VAR3 to be the same as $VAR2, and you don't care about references.

Related

Using a string value with the name of an existing variable to get the value of the existing variable

I am using a bash script in an azure devops pipeline where a variable is created dynamically from one of the pipeline tasks.
I need to use the variable's value in subsequent scripts, I can formulate the string which is used for the variable name, however cannot get the value of the variable using this string. I hope the below example makes it clear on what I need.
Thanks in advance for your help.
PartAPartB="This is my text"
echo "$PartAPartB" #Shows "This is my text" as expected
#HOW DO I GET BELOW TO PRINT "This is my text"
#without using the PartAPartB variable and
#using VarAB value to become the variable name
VarAB="PartAPartB"
VARNAME="$VarAB"
echo $("$VARNAME") #INCORRECT
You can use eval to do this
$ PartAPartB="This is my text"
$ VarAB="PartAPartB"
$ eval "echo \${${VarAB}}"
This is my text
You have two choices with bash. Using a nameref with declare -n (which is the preferred approach for Bash >= 4.26) or using variable indirection. In your case, examples of both would be:
#!/bin/bash
VarAB="PartAPartB"
## using a nameref
declare -n VARNAME=VarAB
echo "$VARNAME" # CORRECT
## using indirection
othervar=VarAB
echo "${!othervar}" # Also Correct
(note: do not use ALLCAPS variable names, those a generally reserved for environment variables or system variables)

Use variable's value to get another variable [duplicate]

I am trying to create an environment variable in bash script, user will input the name of environment variable to be created and will input its value as well.
this is a hard coded way just to elaborate my question :
#!/bin/bash
echo Hello
export varName="nameX" #
echo $varName
export "$varName"="val" #here I am trying to create an environment
#variable whose name is nameX and assigning it value val
echo $nameX
it works fine
it's output is :
Hello
nameX
val
But, I want a generic code. So I am trying to take input from user the name of variable and its value but I am having trouble in it. I don't know how to echo variable whose name is user-defined
echo "enter the environment variable name"
read varName
echo "enter the value to be assigned to env variable"
read value
export "$varName"=$value
Now, I don't know how to echo environment variable
if I do like this :
echo "$varName"
it outputs the name that user has given to environment variable not the value that is assigned to it. how to echo value in it?
Thanks
To get closure: the OP's question boils down to this:
How can I get the value of a variable whose name is stored in another variable in bash?
var='value' # the target variable
varName='var' # the variable storing $var's *name*
gniourf_gniourf provided the solution in a comment:
Use bash's indirection expansion feature:
echo "${!varName}" # -> 'value'
The ! preceding varName tells bash not to return the value of $varName, but the value of the variable whose name is the value of $varName.
The enclosing curly braces ({ and }) are required, unlike with direct variable references (typically).
See https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
The page above also describes the forms ${!prefix#} and ${!prefix*}, which return a list of variable names that start with prefix.
bash 4.3+ supports a more flexible mechanism: namerefs, via declare -n or, inside functions, local -n:
Note: For the specific use case at hand, indirect expansion is the simpler solution.
var='value'
declare -n varAlias='var' # $varAlias is now another name for $var
echo "$varAlias" # -> 'value' - same as $var
The advantage of this approach is that the nameref is effectively just an another name for the original variable (storage location), so you can also assign to the nameref to update the original variable:
varAlias='new value' # assign a new value to the nameref
echo "$var" # -> 'new value' - the original variable has been updated
See https://www.gnu.org/software/bash/manual/html_node/Shell-Parameters.html
Compatibility note:
Indirect expansion and namerefs are NOT POSIX-compliant; a strictly POSIX-compliant shell will have neither feature.
ksh and zsh have comparable features, but with different syntax.

concatenate variables in a bash script

Hi I would like to set a variable by concatenating two other variables.
Example
A=1
B=2
12=C
echo $A$B
desired result being C
however the answer I get is always 12
Is it possible?
UPDATED
Example
A=X
B=Y
D=$A$B
xy=test
echo $D
desired result being "test"
It looks like you want indirect variable references.
BASH allows you to expand a parameter indirectly -- that is, one variable may contain the name of another variable:
# Bash
realvariable=contents
ref=realvariable
echo "${!ref}" # prints the contents of the real variable
But as Pieter21 indicates in his comment 12 is not a valid variable name.
Since 12 is not a valid variable name, here's an example with string variables:
> a='hello'
> b='world'
> declare my_$a_$b='my string'
> echo $my_hello_world
my string
What you are trying to do is (almost) called indirection: http://wiki.bash-hackers.org/syntax/pe#indirection
...I did some quick tests, but it does not seem logical to do this without a third variable - you cannot do concatenated indirection directly as the variables/parts being concatenated do not evaluate to the result on their own - you would have to do another evaluation. I think concatenating them first might be the easiest. That said, there is a chance you could rethink what you're doing.
Oh, and you cannot use numbers (alone or as the starting character) for variable names.
Here we go:
cake="cheese"
var1="ca"
var2="ke"
# this does not work as the indirection sees "ca" and "ke", not "cake". No output.
echo ${!var1}${!var2}
# there might be some other ways of tricking it to do this, but they don't look to sensible as indirection probably needs to work on a real variable.
# ...this works, though:
var3=${var1}${var2}
echo ${!var3}

How can iterate thru enumerated variables in bash?

I have a set of variables, which I obtained thru eval a file.
My variables are named with this pattern:
variable_name_1
variable_name_2
...
variable_name_n
usually those variables contain a filename, so naturally I want to iterate with in this nature:
for cur in variable_name_[i]; do
<do stuff>; done
Is there a way to achieve that functionality?
Yes, using parameter expansion:
#!/bin/bash
variable_name_1="one"
variable_name_2="two"
variable_name_3="three"
for cur in ${!variable_name_*}; do
echo "${cur}=${!cur}"
done
Example run:
$ ./foo.sh
variable_name_1=one
variable_name_2=two
variable_name_3=three
But you might want to reconsider how to obtain those variables, evaling your "config file" (?) is probably not the best choice.

How to Set variables inside a Linux for loop

I'm trying to determine the existing HDDs in each system using a for loop as show below, the problem is when I try to set the variable using the below code i get sda=true: command not found. What is the proper way to do this?
#!/bin/bash
for i in a b c d e f
do
grep -q sd$i /proc/partitions
if [ $? == 0 ]
then
sd$i=true
else
sd$i=false
fi
done
You need to use an array or declare:
declare sd$i=true
I would use an array in this case. For example:
$ i=a
$ sd[$i]=true
$ echo ${sd[a]}
true
As another poster stated, if you want to do this without an array, you can instead make a local variable by using syntax like declare sd$i=true. If you want to make a global variable, use export sd$i=true.
BASH FAQ entry #6: "How can I use variable variables (indirect variables, pointers, references) or associative arrays?": "Assigning indirect/reference variables"

Resources