后续后台部分这个问题。
在bash
I 中可以用于${!FOO}
双重替换,在zsh
${(P)FOO}
.在这两种情况下,老派(hack-y)eval \$$FOO
都有效。
所以,对我来说最聪明、最合乎逻辑的事情是${${FOO}}, ${${${FOO}}}…
双/三/n 替换。为什么这不能按预期工作?
第二:声明\
中的作用是什么eval
?我认为这是一种逃避,让事情变得eval \$$$FOO
不可能。如何使用在每个 shell 中都有效的三重/n 替换?
答案1
必须\
用于防止$$
(当前进程 ID)的扩展。对于三重替换,您需要双重 eval,因此还需要更多转义以避免每个 eval 中不必要的扩展:
#! /bin/bash
l0=value
l1=l0
l2=l1
l3=l2
l4=l3
echo $l0
eval echo \$$l1
eval eval echo \\$\$$l2
eval eval eval echo \\\\$\\$\$$l3
eval eval eval eval echo \\\\\\\\$\\\\$\\$\$$l4
答案2
#!/bin/bash
hello=world
echo=hello
echo $echo ${!echo}
答案3
假设 的值FOO
是有效的变量名(例如BAR
),eval \$$FOO
将 的值拆分BAR
为单独的单词,将每个单词视为通配符模式,并将结果的第一个单词作为命令执行,将其他单词作为参数传递。美元前面的反斜杠使其按字面意思处理,因此传递给eval
内置函数的参数是四字符字符串$BAR
。
${${FOO}}
是一个语法错误。它不执行“双重替换”,因为任何常见 shell 中都没有这样的功能(无论如何都不使用此语法)。在 zsh 中,${${FOO}}
是有效并且是双重替换,但它的行为与您想要的不同:它对 的值执行两次连续的转换FOO
,这两个转换都是恒等转换,所以它只是一种奇特的编写方式${FOO}
。
如果您想将变量的值视为变量,请注意正确引用内容。如果将结果设置为变量会容易得多:
eval "value=\${$FOO}"
答案4
你为什么需要这么做?
您始终可以通过几个步骤来完成此操作,例如:
eval "l1=\${$var}"
eval "l2=\${$l1}"
...
或者使用如下函数:
deref() {
if [ "$1" -le 0 ]; then
eval "$3=\$2"
else
eval "deref $(($1 - 1)) \"\${$2}\" \"\$3\""
fi
}
然后:
$ a=b b=c c=d d=e e=blah
$ deref 3 a res; echo "$res"
d
$ deref 5 a res; echo "$res"
blah
FWIW,在zsh
:
$ echo ${(P)${(P)${(P)${(P)a}}}}
blah