2

In bash, I understand we can have variable indirect expansion via two ways:

  • Using declare: declare -n foo=bar
  • Using the ${!..} expansion.

We can combine both:

declare -n foo=SHELL
bar=foo
echo ${!bar}

gives:

/bin/bash

Is it possible to extend this to more levels?


It's mostly as for writing obfuscated code - some of my friends are challenging each other.

0

Actually, there is a further method to do indirections in Bash, at least effectively: If you have a=1 and b=a, you can get the value of a through b like so:

eval echo \${$b}

This can be nested several times:

$ a=1; b=a; c=b; d=c
$ eval eval eval echo \\\\\\\${\\\${\${$d}}}
1

Here are the rules to find the right number of backslashes on each level:

  1. On the innermost level, no backslashes are used.
  2. On any other level, use 2 n + 1 backslashes, where n is the number of backslashes that are used on the next inner level.

Rationale: Rule 1 is trivial. Rule 2 comes from the fact that you have to apply one backslash more that in the next inner level while you have to escape all those that are not consumed in the current level, i.e. all but one.

As a consequence, the number of needed backslashes diverges exponentially with increasing number of levels so that nesting reaches its limit rather soon for this method.

But one has to emphasize here that this limit is of rather academic nature. In practice, where one has to respect needs such like maintainability, one typically does not want to handle more than two or three levels of indirection in one single expression—no matter which method of indirection is used.

Instead, one can resolve higher levels of indirection by using a loop to iterate something like

value=${variable}
variable=${!value}

a number of times that is suitable for the given application.

0

There is a (large) indirection allowed directly in arithmetic expansion for only numbers.

$ a=123 b=a c=b d=c e=d ; echo $((e))
123

you could expand it with declare:

$ jj=123; for ii in {a..f}{a..z}; do declare $ii=$jj; jj=$ii; done; echo "$((ii))"
123

But it is not infinite:

$ jj=123; for ii in {a..z}{a..z}; do declare $ii=$jj; jj=$ii; done; echo "$((ii))"
bash: tz: expression recursion level exceeded (error token is "tz")

Is that enough?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy