Combining a variable value and string to form another variable

20,028

Solution 1

As per the previous answer, you can use eval for this.

eval [arg ...] The args are read and concatenated together into a single com‐ mand. This command is then read and executed by the shell, and its exit status is returned as the value of eval. If there are no args, or only null arguments, eval returns 0. (from bash man page)

However, this is one of those bad programming habits that you need to be very aware of and use as little as possible. It can normally be avoided for something more elegant, less error-prone and easier to debug.

var1=host
eval echo ${var1}_file # print contents of $host_file

Solution 2

If you have variables named as a combination of some proper name, and related attributes you should probably use associative arrays instead. Assuming you have Bash 4.x, ksh or zsh, that is. See a page or another on BashGuide. (Actually structures like in C would be nice, but you can't really get that with Bash.)

That is, to store a URL and a port for the hosts/clusters oregon and arizona, don't make four variables arizona_url, arizona_port, oregon_url, oregon_port, but instead something like this:

typeset -A urls ports
urls[oregon]="http://..."
urls[arizona]="http://..."
ports[oregon]=1234
ports[arizona]=2345

and then use those with "${urls[$hostname1]}", "${ports[$hostname]}" etc.

Solution 3

I can't really see why you would not want to use variable indirection unless you are writing a sh (not bash) script.

As has been mentioned, eval will work, but is generally frowned upon as its use has the potential to be dangerous, especially when evaluating user-supplied data without careful sanitation.

Another way of achieving the same effect is to use name-reference variables (available in bash since version 4.3).

var1=host

declare -n nameref="${var1}_file"

nameref="something something"

printf '%s\n' "$host_file"

This would output the string something something. Using typeset -n in place of declare -n would make it work in both bash and in ksh93.

Share:
20,028

Related videos on Youtube

Rajesh Reddy B
Author by

Rajesh Reddy B

Updated on September 18, 2022

Comments

  • Rajesh Reddy B
    Rajesh Reddy B over 1 year

    I want to reference a bash variable from a variable without using:

    echo "${!VARNAME}"
    

    Any ideas? Since I want to use the variable on fly and many such references are there, I can't declare them to another variable and use it.

    Example:

    var1=host
    ${var1}_file ----> host_file is another variable that i want to call in a command. 
    
    • user unknown
      user unknown over 6 years
      What is the reason not to use "${!VARNAME}" ?
    • Rajesh Reddy B
      Rajesh Reddy B over 6 years
      What we generally do is add concatenated variable and string to a variable and use that variable in "${!VARNAME}" . But i do not want to pass concatenated value to another variable but use it directly. something like ` ls host_file`. Like this i have to use multiple variables in a single command.
    • ilkkachu
      ilkkachu over 6 years
      @RajeshReddyB, yes, you explained in the question you want to generate variable names on the fly. I was trying to ask why. This has the smell of asking for X when you're actually trying to do Y. (See here and here)
    • Rajesh Reddy B
      Rajesh Reddy B over 6 years
      I'm actually trying to run execute below command. hadoop jar $DistcpJar -libjars $DistcpAclLibJar -Ddfs.encryption.key.provider.uri=${DestCluster}_${KmsUrl} -sourceconf $SourceConf -pugb -skipcrccheck -update hdfs://$(${SourceCluster}_NameService):${SourceCluster}_Name‌​ServicePort/$Source hdfs://${DestCluster}_NameService:${DestCluster}_NameService‌​Port/$DestLocation ------------------- where Source cluster is a positional parameter i pass to the main script and combining with another name forms a different variable.
  • Rajesh Reddy B
    Rajesh Reddy B over 6 years
    I have actually tried this but declare doesn't have -n option and couldn't go further.
  • Kusalananda
    Kusalananda over 6 years
    @RajeshReddyB This indicates that your bash is older than release 4.3.
  • Stéphane Chazelas
    Stéphane Chazelas over 5 years
    ${!var1} is as dangerous as eval if the content of $var1 may be under the control of an attacker. That code is not correct, it should have been eval 'echo "${'"$var1"'_file}"'