Multi layer variable substitution in shell.. possible? - shell

I have multiple variables in a shell script; i was trying to save some code duplication and wanted to do something like following
# variables
FLAG=SIM
SIM_ICR_KEY_VAL="http://www.example.com/simi/icr"
REAL_ICR_KEY_VAL="http://www.example.com/real"
Based on the FLAG value i want to access the correct variable (without using IF's)
When i try this it echos the variable name & not the value itself.
echo $(echo ${FLAG}_ICR_KEY_VAL)
On further note; i need to use these substitutions inline in a sed statememt:
sed "s!${ISTR_KEY}=.*!${ISTR_KEY}=${SIM_ISTR_KEY_VAL}!" > tmp.file
... i am not sure its possible or not, please suggest

Reflection can be achieved with the infamous eval:
eval thisvar=\$${FLAG}_INC_KEY_VAL;
echo "We are using $thisvar"
Whenever you find yourself dynamically synthesizing a variable name, though, you are probably Doing It Wrong. You should consider alternatives like arrays:
ICR_KEY_VAL[0]="http://www.example.com/simi/icr"
ICR_KEY_VAL[1]="http://www.example.com/real"
SIM=0
echo ${ICR_KEY_VAL[$SIM]}

I don't know how to do it directly, but in bash you can do it indirectly:
FLAG=SIM
SIM_ICR_KEY_VAL="http://www.example.com/simi/icr"
REAL_ICR_KEY_VAL="http://www.example.com/real"
FLAG_ICR_KEY_VAL=${FLAG}_ICR_KEY_VAL
sed "s!${ISTR_KEY}=.*!${ISTR_KEY}=${!FLAG_ISTR_KEY_VAL}!" > tmp.file

Related

Two Bash substitutions in one statement?

In Bash you can substitute an empty or undefined variable with this:
${myvar:-replacement}
You can also replace substrings in variables like this:
${myvar//replace this/by this}
Now I want to combine both substitutions into one: If variable is undefined, set it to replacement, otherwise replace a part of it with something else.
I can write this in two lines without problems.
myvar=${myvar:-replacement}
myvar=${myvar//replace this/by this}
or to more closely reflect my business logic:
if [[ -n "${myvar:-}" ]]; then
myvar="${myvar//replace this/by this}"
else
myvar="replacement"
fi
Is there a way to combine both substitutions into one statement / one line?
I have tried this without success:
myvar=${${myvar:-replacement}//replace this/by this} # bad substitution
I am using set -u in my scripts so that they error out when I use undefined variables. That's why I need the first sub on undefined var.
As far as I know this is not possible in Bash.
The best thing you could do is writing them on multiple lines, or use an NOP command, or use utilities:
myvar=${myvar:-replacement}
myvar=${myvar/src/dest}
myvar=$(sed 's/src/dest/g' <<< ${myvar:-defaulttext})

Storing bash output into a variable using eval

I have a line of code
eval echo \$$var
which prints a string. How can I store this string into a variable?
Like this:
eval c=\$$var
a better, safer way is to use indirection:
c=${!var}
newVariable=$(eval echo \$$var)
You can try this: It worked for me on bash.
c=$(eval echo \${$var})
Example: If HOME is the environment variable that contains your home directory like /export/users/john, then embedding a variable within another variable and then unpacking that combination would work like this:
var=HOME
c=$(eval echo \${$var})
echo $c
/export/users/john
While this might look unnecessarily convoluted it will be useful in certain scenarios.
This can achieved by using the back quote syntax : ` `
c=`$var`

variable substitution removing quotes

I seem to have some difficulty getting what I want to work. Basically, I have a series of variables that are assigned strings with some quotes and \ characters. I want to remove the quotes to embed them inside a json doc, since json hates quotes using python dump methods.
I figured it would be easy. Just determine how to remove the characters easy and then write a simple for loop for the variable substitution, well it didn't work that way.
Here is what I want to do.
There is a variable called "MESSAGE23", it contains the following "com.centrify.tokend.cac", I want to strip out the quotes, which to me is easy, a simple echo $opt | sed "s/\"//g". When I do this from the command line:
$> MESSAGE23="com."apple".cacng.tokend is present"
$> MESSAGE23=`echo $MESSAGE23 | sed "s/\"//g"`
$> com.apple.cacng.tokend is present
This works. I get the properly formatted string.
When I then try to throw this into a loop, all hell breaks loose.
for i to {1..25}; do
MESSAGE$i=`echo $MESSAGE$i | sed "s/\"//g"`
done
This doesn't work (either it throws a bunch of indexes out or nothing), and I'm pretty sure I just don't know enough about arg or eval or other bash substitution variables.
But basically I want to do this for another set of variables with the same problems, where I strip out the quotes and incidentally the "\" too.
Any help would be greatly appreciated.
You can't do that. You could make it work using eval, but that introduces another level of quoting you have to worry about. Is there some reason you can't use an array?
MESSAGE=("this is MESSAGE[0]" "this is MESSAGE[1]")
MESSAGE[2]="I can add more, too!"
for (( i=0; i<${#MESSAGE[#]}; ++i )); do
echo "${MESSAGE[i]}"
done
Otherwise you need something like this:
eval 'echo "$MESSAGE'"$i"'"'
and it just gets worse from there.
First, a couple of preliminary problems: MESSAGE23="com."apple".cacng.tokend is present" will not embed double-quotes in the variable value, use MESSAGE23="com.\"apple\".cacng.tokend is present" or MESSAGE23='com."apple".cacng.tokend is present' instead. Second, you should almost always put double-quotes around variable expansions (e.g. echo "$MESSAGE23") to prevent parsing oddities.
Now, the real problems: the shell doesn't allow variable substitution on the left side of an assignment (i.e. MESSAGE$i=something won't work). Fortunately, it does allow this in a declare statement, so you can use that instead. Also, when the sees $MESSAGE$i it replaces it will the value of $MESSAGE followed by the value of $i; for this you need to use indirect expansion (`${!metavariable}').
for i in {1..25}; do
varname="MESSAGE$i"
declare $varname="$(echo "${!varname}" | tr -d '"')"
done
(Note that I also used tr instead of sed, but that's just my personal preference.)
(Also, note that #Mark Reed's suggestion of an array is really the better way to do this sort of thing.)

how to access an automatically named variable in a Bash shell script

I have some code that creates a variable of some name automatically and assigns some value to it. The code is something like the following:
myVariableName="zappo"
eval "${myVariableName}=zappo_value"
How would I access the value of this variable using the automatically generated name of the variable? So, I'm looking for some code a bit like the following (but working):
eval "echo ${${myVariableName}}"
(... which may be used in something such as myVariableValue="$(eval "echo ${${myVariableName}}")"...).
Thanks muchly for any assistance
If you think this approach is madness and want offer more general advice, the general idea I'm working on is having variables defined in functions in a library with such names as ${usage} and ${prerequisiteFunctions}. These variables that are defined within functions would be accessed by an interrogation function that can, for instance, ensure that prerequisites etc. are installed. So a loop within this interrogation function is something like this:
for currentFunction in ${functionList}; do
echo "function: ${currentFunction}"
${currentFunction} -interrogate # (This puts the function variables into memory.)
currentInterrogationVariables="${interrogationVariables}" # The variable interrogationVariables contains a list of all function variables available for interrogation.
for currentInterrogationVariable in ${currentInterrogationVariables}; do
echo "content of ${currentInterrogationVariable}:"
eval "echo ${${currentInterrogationVariable}}"
done
done
Thanks again for any ideas!
IIRC, indirection in bash is by !, so try ${!myVariableName}
Try:
echo ${!myVariableName}
It will echo the variable who's name is contained in $myVariableName
For example:
#!/bin/bash
VAR1="ONE"
VAR2="TWO"
VARx="VAR1"
echo ${VARx} # prints "VAR1"
echo ${!VARx} # prints "ONE"

Shell script variable problem

I'm trying to write a shell script to automate a job for me. But i'm currently stuck.
Here's the problem :
I have a variable named var1 (a decreasing number from 25 to 0
and another variable named
var${var1} and this equals to some string.
then when i try to call var${var1} in anywhere in script via echo it fails.
I have tried $[var$var1], ${var$var} and many others but everytime it fails and gives the value of var1 or says operand expected error.
Thanks for your help
It's probably better if you use an array, but you can use indirection:
var25="some string"
var1=25
indirect_var="var$var1"
echo ${!indirect_var} # echoes "some string"
There's only one round of variable expansion, so you can't do it directly. You could use eval:
eval echo \${var$var1}
A better solution is to use an array:
i=5
var[$i]='foo'
echo ${var[$i]}
It sounds like you need bash variable indirection. Take a look at the link below.
http://mywiki.wooledge.org/BashFAQ/006

Resources