for 循环中的 Bash 赋值变量返回“未找到命令”

for 循环中的 Bash 赋值变量返回“未找到命令”

在 Bash 中,我想:

  1. 创建 3 个变量,名称为 ID1、ID2、ID3
  2. 变量将分别被分配字符串值 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_COUNTin的值为 2,则它ID${ID_COUNT}=ID${ID_COUNT}_VALUE;会被扩展。然而,在执行命令时,变量已经被检测到,所以你现在拥有的是ID2=ID2_VALUE细绳其中有一个等号。 shell 将继续尝试执行该字符串,就像它是命令名称一样。

相关内容