1
HOST_NAME_="localhost:8080" 
HOST_NAME_stg="stg.com:8080"
HOST_NAME_qa="qa.com:8080"
HOST_NAME=${!"HOST_NAME_$1"}

echo -n ${HOST_NAME}

I get the error bad substitution.But I want stg.com:8080 to printed if the argument passed is stg.How do I do that

mklement0
  • 382,024
  • 64
  • 607
  • 775
Abhijeet Kushe
  • 2,477
  • 3
  • 26
  • 39

2 Answers2

6

Note: Given your use of ${!...} to refer to a variable indirectly, I assume that you're using bash - POSIX-features-only shells and many others do NOT support this feature (at least with this syntax).

Try the following:

HOST_NAME_="localhost:8080" 
HOST_NAME_stg="stg.com:8080"
HOST_NAME_qa="qa.com:8080"

HOST_NAME_INDIRECT=HOST_NAME_$1

HOST_NAME=${!HOST_NAME_INDIRECT}

echo -n "${HOST_NAME}"

When referencing a variable indirectly with ${!...}, the argument containing the target variable name must itself be a variable, not a string literal, hence the intermediate variable $HOST_NAME_INDIRECT.

Also consider avoiding all-uppercase variable names to avoid potential conflicts with standard environment variables (such as $HOSTNAME) and special shell variables (such as $SECONDS).


Here's how various popular shells do variable indirection:

Assume the following two variables:

a='value of a'
nameOfA='a'
  • bash

     echo "${!nameOfA}" # -> 'value of a'
    
     # bash 4.3+
     declare -n aliasOfA='a'  # in functions: `local -n`
     echo "$aliasOfA"         # same as `echo "$a"` -> 'value of a'
    
  • zsh

    echo "${(P)nameOfA}"  # -> 'value of a'
    
  • ksh 93+:

     nameref aliasOfA='a'  # same as `typeset -n`
     echo "$aliasOfA"      # same as `echo "$a"` -> 'value of a'
    
  • sh (POSIX-features-only shells)

     eval echo \"'$'$nameOfA\"  # -> 'value of a'
    

Caveat: Using eval is potentially unsafe. If $nameOfA contained something like 'a; $(rm *)', the rm command would execute too.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thanks for providing such a detailed answer.This does solve my problem but I would like to know more details about why eval is unsafe.I looked at some links of stackoverflow which talk about eval but they just add to the ambiguity. If you know some good sources which talk about eval can you post it here. Thanks – Abhijeet Kushe Apr 20 '14 at 19:04
  • 1
    @AbhijeetKushe: In a nutshell: a string passed to `eval` can contain _any_ command. If you don't have full control over that string - e.g., if it is passed from a calling script - it may contain commands that either inadvertently or maliciously do things you do not want or expect. Say someone passed `qa; $(rm ...)` instead of `qa` as `$1` to your script. It's a contrived example, but shows you the principle of how unwanted things can happen. This is not to say that `eval` must _never_ be used - just be aware of its dangers and limit use to carefully controlled circumstances. – mklement0 Apr 20 '14 at 23:17
0

Thanks for the reply.Yeah using a temporary variable does solve the problem.But I figured out if to do this it serves the purpose but it is slightly complicated

eval "HOST_NAME=\$HOST_NAME_$2"
Abhijeet Kushe
  • 2,477
  • 3
  • 26
  • 39
  • 1
    While your version has the advantage of working in all Bourne-like shells, it's potentially unsafe, because it uses `eval`. Thus, in `bash` I suggest you use the `${!...}` approach. – mklement0 Apr 19 '14 at 16:08