shell/bash while read export variable 不适用于替代

shell/bash while read export variable not working for subtitute

我想从文件中导出变量。这是我的文件

cat file.txt
VERSION=1.0.0
LOCATION=USA
NAME=sample
ENVIRONMENT=$ENV

我使用这个 while 循环导出该文件上的所有变量

while read vars; do export $vars;done < file.txt

所有变量都已成功导出,ENVIRONMENT除外 我得到这个值,ENVIRONMENT=$ENV(预期值为 ENVIRONMENT=staging)。

printenv | grep ^ENV
ENV=staging

我的问题是,为什么 substitute 在使用 while loop 时不起作用,但如果我们手动导出 (e.g export ENVIRONMENT=$ENV) 则它起作用了??

实际上有很多方法可以从文件中导出变量,例如我可以使用 envsubst < file > file1 然后执行 while loop,但我只需要对上述情况进行解释。

展开的顺序是described in POSIX:

The order of word expansion shall be as follows:

  1. Tilde expansion (see Tilde Expansion), parameter expansion (see Parameter Expansion), command substitution (see Command Substitution), and arithmetic expansion (see Arithmetic Expansion) shall be performed, beginning to end. See item 5 in Token Recognition.

  2. Field splitting (see Field Splitting) shall be performed on the portions of the fields generated by step 1, unless IFS is null.

  3. Pathname expansion (see Pathname Expansion) shall be performed, unless set -f is in effect.

  4. Quote removal (see Quote Removal) shall always be performed last.

对于参数扩展,tl;dr 是:

${parameter}

The value, if any, of parameter shall be substituted.

您会注意到该定义不是递归的或多遍的。不存在“5.返回步骤1重复直到无法进行进一步的扩展”,或者“参数的值(如果有的话)应该被替换,并且重复该过程直到找不到更多的参数扩展”。

这意味着 export $vars 将在第 1 步中展开 $vars,但不会重复该步骤,因此 $ENV 保持不变。

这也是所有其他编程语言的基本工作方式,例如Java:

String foo="bar";
String bar="baz";
// Prints `bar` without recursively resolving it into `baz`
System.out.println(foo);