在 Bash 中,我想:
- 创建 3 个变量,名称为 ID1、ID2、ID3
- 变量将分别被分配字符串值 ID1_VALUE、ID2_VALUE 和 ID3_VALUE
我创建了一个像这样的for循环
for ID_COUNT in 1 2 3; do
ID${ID_COUNT}=ID${ID_COUNT}_VALUE;
done;
当代码片段运行时,我得到了这个
ID1=ID1_VALUE: command not found
ID2=ID2_VALUE: command not found
ID3=ID3_VALUE: command not found
并且值 ID1、ID2、ID3 均未设置(set | grep ID1
什么也不显示)。
有人可以详细解释一下发生了什么吗?
答案1
显然,bash
它特别关注命令行的解释,它在评估使用的变量之前发现变量分配。基本上,变量赋值要求名称部分是专有名称,而不是通过求值得出的名称。但有一个“nameref”的概念,其中一个变量有一个变量名作为值,然后对它的赋值变成了对其值命名的变量的赋值。在您的示例中,它看起来类似于以下内容:
for ID_COUNT in 1 2 3; do
declare -n X=ID${ID_COUNT}
X=ID${ID_COUNT}_VALUE;
done;
当然,使用eval
命令也可以实现同样的效果,该命令将其参数作为调用上下文中的命令进行评估。使用它看起来如下:
for ID_COUNT in 1 2 3; do
eval ID${ID_COUNT}=ID${ID_COUNT}_VALUE;
done;
如前所述,使用export
具有类似的效果,此外还可以将变量导出到子流程,这是其主要功能。
答案2
如果您使用数组来实现当前和未来的脚本,效果会更好:
#!/bin/bash
for i in 1 2 3; do
id[i]="ID${i}_VALUE"
done
echo 'contents of the array "id":'
printf '\t%s\n' "${id[@]}"
该脚本的输出将是
contents of the array "id":
ID1_VALUE
ID2_VALUE
ID3_VALUE
脚本中的循环也可以替换为
id=( "ID"{1..3}"_VALUE" )
它使用大括号扩展来创建数组。
在你的代码中发生的情况是,如果变量$ID_COUNT
in的值为 2,则它ID${ID_COUNT}=ID${ID_COUNT}_VALUE;
会被扩展。然而,在执行命令时,变量已经被检测到,所以你现在拥有的是ID2=ID2_VALUE
细绳其中有一个等号。 shell 将继续尝试执行该字符串,就像它是命令名称一样。