Search code examples
shellvariable-expansionindirection

Understanding indirection


I'm currently working on cleaning up some shell scripts. While doing that, I came across something that looks like this:

if [ ${#VARA} -eq 0 ] || [ ${#$VARB} -eq 0 ] || [ ${$VARC} -eq 0 ]; then
  ...
fi

As you can see, there are three different types of things going on here with variables: ${#V}, ${#$V}, and ${$V}. I would love an explanation of each of these please. (Plus Shellcheck is complaining about the last one.)


Solution

  • This syntax is part of POSIX (thence Bash) shell parameter expansion. It counts number of characters for a variable :

    $ myvar="foo" && echo ${#myvar}
    3
    

    The last two ones ${#$VARB} and ${$VARC} have not a valid syntax. You cannot declare a variable this way.

    Quite similar to your ${$VARC} is the valid \$$myvar, used for indirect reference with eval or echo. This syntax refers to the literal string "$foo" (when myvar="foo"). As @chepner mentionned, because of eval, it's not recommended to use it. The Bash 2.0 introduced the ${!myvar} syntax for indirect variable reference that is a much preferable alternative.

    Note : you should avoid uppercase for variable names not to confuse with shell variables which are also uppercased by convention.