Search code examples
shellunixindirection

Assign value to a variable in unix dynamically - variable indirection


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


Solution

  • 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.