在 bash 中,我知道我们可以通过两种方式进行变量间接扩展:
- 使用
declare
:declare -n foo=bar
- 使用
${!..}
扩展。
我们可以将两者结合起来:
declare -n foo=SHELL
bar=foo
echo ${!bar}
给出:
/bin/bash
是否可以将其扩展到更多级别?
这主要是关于编写混淆代码——我的一些朋友正在互相挑战。
答案1
实际上,在 Bash 中还有一种更进一步的方法可以进行间接寻址,至少是有效的:如果你有a=1
和,你可以像这样获取throughb=a
的值:a
b
eval echo \${$b}
这可以嵌套多次:
$ a=1; b=a; c=b; d=c
$ eval eval eval echo \\\\\\\${\\\${\${$d}}}
1
以下是在每个级别上找到正确数量的反斜杠的规则:
- 在最内层,不使用反斜杠。
- 在任何其他级别,使用 2n+ 1 个反斜杠,其中n是下一个内部级别使用的反斜杠的数量。
理由:规则 1 是微不足道的。规则 2 来自以下事实:您必须在下一个内部级别中多应用一个反斜杠,同时必须转义所有在当前级别中未消耗的内容,即除了一个之外的所有内容。
因此,随着层数的增加,所需反斜杠的数量呈指数级分布,因此这种方法的嵌套很快就达到了极限。
但这里必须强调的是,这一限制具有相当学术性。在实践中,当人们必须尊重诸如可维护性之类的需求时,人们通常不希望在一个表达式中处理多于两层或三层的间接——无论使用哪种间接方法。
相反,我们可以通过使用循环来迭代类似的内容来解决更高级别的间接寻址
value=${variable}
variable=${!value}
适合给定应用的多次。
答案2
仅允许在算术扩展中直接使用(大)间接寻址数字。
$ a=123 b=a c=b d=c e=d ; echo $((e))
123
你可以用声明来扩展它:
$ jj=123; for ii in {a..f}{a..z}; do declare $ii=$jj; jj=$ii; done; echo "$((ii))"
123
但它不是无限的:
$ 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")
够了吗?