1

Sorry, that was all too confusing, (my bad)
Let me try to explain again, but with a more simple example:

#define a new var and export it to the "env":
export VAR_ONE=thisIsVarOne
# check if it was created:
env | grep VAR_ONE      #this displays: "VAR_ONE=thisIsVarOne"
# use it in a simple echo command:
echo VAR_ONE=$VAR_ONE  #this displays: "VAR_ONE=thisIsVarOne"

create a new var with the name that contains the value of VAR_ONE ("newvarthisIsVarOne") in its name:

export newvar${VAR_ONE}="somePrefix${VAR_ONE}"

verify if it has been created:

env | grep newvar # this displays: "newvarthisIsVarOne=somePrefixthisIsVarOne"

Now my question:

How do I use that new, syntetic, variable?
Please note that: env | grep newvar shows that there has been created a variable with the name newvar${VAR_ONE}

But I can't address that new variable, e.g. in an echo command. I tried: echo ${newvar${VAR_ONE}}
But that gave me bash: ${newvar${VAR_ONE}}: bad substitution

Constraints:

  1. The value of VAR_ONE can change, so I can't use that to address the newly created variable
  2. I can't declare a new variable with a static name. For usage, further in the script, I need the keyword VAR_ONE as part of the name of the newly created variable. The name of the variable needs to be something like: newvar${VAR_ONE}

Thank you in advance ChriV

  • turn on shell debugging with set -x (set +x to turn off) and you'll see lines begingging with + where all shell pre-processing is complete, so you'll see how the shell interprets echo newvar${VAR}=${newvar${VAR}}, for example and then the output from executing that command (the normal output). – shellter Nov 17 '23 at 18:24

4 Answers4

0

Do not use a $ to affect a variable in bash:

var_name=value
var_name1="value with spaces"
var_name2='value with $ or special characters'

To get the value of a variable, use a $ before its name:

echo "var_name=$var_name"
echo "var_name1=use_braces_to_protect_the variable_name_${var_name1}_"
my_new_var="$var_name2"

If your variable contains the name of another variable, you must use an exclamation point before the variable name into braces:

my_var=spam
the_var_name=my_var
echo "the value is '${!the_var_name}'"

So your program will be:

#! /bin/bash

VAR1=thisIsVar1 #VAR2=thisIsVar2 VAR3=thisIsVar3 VAR_NAMES=($VAR1 $VAR2 $VAR3)

echo "VAR_NAMES=" "${VAR_NAMES[@]}"

for VAR_NAME in "${VAR_NAMES[@]}"; do echo echo "VAR_NAME=$VAR_NAME"

NEW_VAR_NAME="newvar$VAR_NAME"
echo "NEW_VAR_NAME=$NEW_VAR_NAME"

export "${NEW_VAR_NAME}"="somevalue ${VAR_NAME}"
echo "${NEW_VAR_NAME}=${!NEW_VAR_NAME}"

done

UPDATE

You could also create a hash table (associative array) with new var_name/var_value as key/value:

#! /bin/bash

VAR1=thisIsVar1 #VAR2=thisIsVar2 VAR3=thisIsVar3 VAR_NAMES=($VAR1 $VAR2 $VAR3)

echo "VAR_NAMES=" "${VAR_NAMES[@]}"

declare -A NEW_VAR_NAMES=()

for VAR_NAME in "${VAR_NAMES[@]}"; do echo echo "VAR_NAME=$VAR_NAME"

NEW_VAR_NAME="newvar$VAR_NAME"
echo "NEW_VAR_NAME=$NEW_VAR_NAME"

export "${NEW_VAR_NAME}"="somevalue ${VAR_NAME}"
echo "${NEW_VAR_NAME}=${!NEW_VAR_NAME}"

NEW_VAR_NAMES+=(["${NEW_VAR_NAME}"]=${!NEW_VAR_NAME})

done

echo echo "${NEW_VAR_NAMES[@]@A}"

for new_var_name in "${!NEW_VAR_NAMES[@]}"; do echo "new_var_name is ${new_var_name} and its content is '${NEW_VAR_NAMES[$new_var_name]}'" done

  • Hi @Arnaud
    Thank you for your answer
    I do not want to create a new var called NEW_VAR_NAME I want to create a new VAR that contains the value of another var in its name e.g.
    export newvar${VAR_ONE}="somePrefix${VAR_ONE}"    
    # check if it was created  
    env | grep newvar  # this displays: "newvarthisIsVarOne=somePrefixthisIsVarOne"  
    

    But how do I address this new var in e.g. an "echo" command?

    – Chris V. Nov 17 '23 at 19:28
  • In my example, the new var names are "newvar$VAR_NAME", not "NEW_VAR_NAME". "NEW_VAR_NAME" is a variable who contains the name of the new var. So the content of new var name is addressable with "${!NEW_VAR_NAME}". You cannot use nested braces like this "${newvar${VAR_NAME}}" – Arnaud Valmary Nov 17 '23 at 19:39
  • So, I successfully created a var called "newvar${VAR_ONE}". This is my intention. This variable exists, I can verify with env | grep newvar. My challenge is: how do I address this new variable e.g. in an "echo" statement? – Chris V. Nov 17 '23 at 19:45
  • echo $newvarthisIsVar1. I don't really understand where is the problem – Arnaud Valmary Nov 17 '23 at 20:25
  • because $newvarthisIsVar1 assumes you know the content of $VAR_ONE; which I don't – Chris V. Nov 17 '23 at 20:33
  • I have updated my response with the construction of a associative array who contains all variables names and contents – Arnaud Valmary Nov 17 '23 at 20:42
0

Setup:

export VAR_ONE=thisIsVarOne

With bash 4.3+ you can use a nameref (declare -n):

$ declare -n _var="newvar${VAR_ONE}"            # nameref; define new var name and associate with nameref variable '_var' (can be any valid variable name)
$ _var="somePrefix${VAR_ONE}"                   # assign value to nameref

$ echo "${!_var}" # show nameref association newvarthisIsVarOne

$ echo "${_var}" # show value somePrefixthisIsVarOne

$ echo "${newvarthisIsVarOne}" # explicitly reference new variable by name somePrefixthisIsVarOne

  • thank you, but I want the name of my new var to contain the content of VAR_ONE. I don't want to create _var of any other static name – Chris V. Nov 17 '23 at 19:50
  • So, I successfully created a var called "newvar${VAR_ONE}".
    This is my intention. This variable exists, I can verify with env | grep newvar. My challenge is: how do I address this new variable e.g. in an "echo" statement? –
    – Chris V. Nov 17 '23 at 19:55
  • the new variable name does contain the content of VAR_ONE, see the last echo which verifies the new variable (named as desired) exists ; in a separate comment you asked how you can go about referencing the newly created variable ... this shows how you can reference that new variable via the nameref, see echo "${_var}" – markp-fuso Nov 17 '23 at 19:57
  • 1
    I'm sorry to take so much of your time. I'm a +60y old engineer who never had any coding class in his life. I am trying to understand, but my 2 brain-cells are boiling now.
    I understand that last echo... but in my case, I don't know the contents of VAR_ONE (being "thisIsVarOne"). In your last echo, you are using that contents.
    – Chris V. Nov 17 '23 at 20:04
  • My new var has the name newvar${VAR_ONE}. This is confirmed by env | grep newvar. My challenge is how do I use it in an echo command. I do not know the contents of VAR_ONE, so I cannot use echo "${newvarthisIsVarOne}" – Chris V. Nov 17 '23 at 20:07
  • the last echo is merely showing that the variable was created, the next-to-last echo shows use of the nameref ... notice the last two echo commands generate the same ouptut; the nameref functions similiar to a file/symlink; alternatively, think of the nameref as a logical name to a physical variable; if I later run declare -n _var="newvar${SOME_OTHER_VAR}" then _var will now point to a different/new variable (and it's associated value) – markp-fuso Nov 17 '23 at 20:08
  • I've created a 2nd answer that makes use of an associateve array which should be easier (?) to understand – markp-fuso Nov 17 '23 at 20:11
  • 1
    re: nameref ... imagine you have 3 brothers (Larry, Moe, Curly), the label brother would be similar to a nameref; if you establish that brother=Moe then you can proceed to reference Moe by the label 'brother' ... brother can you spare a dime, how old are you brother; now suppose you establish that brother=Larry then you can proceed to reference Larry by the label 'brother' ... brother can you spare a dime, how old are you brother; clear as mud? :-) – markp-fuso Nov 17 '23 at 20:16
  • regarding the one-but-last echo: that uses a variable called _var, that you created here. For my script, I need to use a variable that is called newvar${VAR_ONE} because it is in a loop and it should create things like newvar${OTHER_VAR} and newvar${ANOTHER_VAR}. I need this reference to VAR_ONE, OTHER_VAR, and ANOTHER_VAR in the name. I can't use _var anything static. PS: thank you for your time to create the "associative array" approach, but I'm afraid that goes way beyond my understanding – Chris V. Nov 17 '23 at 20:19
  • re: 3 different variables ... use 3 namerefs (eg, _var1, _var2, _var3; or brother1, brother2, brother3); the associative array approach allows you to do exactly what you've stated you want to do, but with a slightly different approach to piecing the two parts (newvar ${VAR_ONE) together – markp-fuso Nov 17 '23 at 20:23
0

Setup:

export VAR_ONE=thisIsVarOne

An alternative using an associative array:

$ unset      newvar
$ declare -A newvar

$ newvar[${VAR_ONE}]="somePrefix${VAR_ONE}"

$ typeset -p newvar declare -A newvar=([thisIsVarOne]="somePrefixthisIsVarOne" )

$ echo "${newvar[${VAR_ONE}]}" somePrefixthisIsVarOne


In a comment OP has stated the need to reference multiple variables, eg, newvar${VAR_ONE}, newvar${OTHER_VAR} and newvar${ANOTHER_VAR}.

This approach with the associative array will work as long as the 3 variables (VAR_ONE, OTHER_VAR and ANOTHER_VAR) have different values, otherwise duplicate values will lead to a single array entry being created (with the latest assignment overwriting the previous assignment).

If the 3 variables could have the same value then another approach would be to use literals for the associative array's indices, eg:

#### instead of:

$ newvar[${VAR_ONE}]="somePrefix${VAR_ONE}"

$ typeset -p newvar declare -A newvar=([thisIsVarOne]="somePrefixthisIsVarOne" )

we use:

$ newvar[VAR_ONE]="somePrefix${VAR_ONE}"

$ typeset -p newvar declare -A newvar=([VAR_ONE]="somePrefixthisIsVarOne" )

0

To access a shell variable without using a separate variable (for either the ${!pointer} syntax or a nameref) the only solution is to use eval, for example

eval "echo \$newvar$VAR_ONE"

-- but this is dangerous it you ever make a mistake, which in practice all people who are humans do.

But for an environment variable which export creates, you can use a child process to do the lookup. In particular awk is POSIX and usually present on most systems that have bash:

    awk -v name=newvar$VAR_ONE 'BEGIN{printf "%s",ENVIRON[name]}'
    # or simpler {print ENVIRON[name]} adds newline which may be okay,
    # e.g. if you use this in $(...) or `...` which removes newline
    # or _instead of_ an echo command because echo also adds newline

Even simpler, many systems have printenv and you can just do printenv newvar$VAR_ONE -- which also adds newline.