使用 Sub-shell 评估函数时环境变量不可见

Environment Variable Not Visible when Evaluating a Function with a Sub-shell

这是我正在编写的更复杂脚本的一个最小示例。我想要做的关键是让 $FOO 对函数 foo.

第二行中的子 shell 可见

然而,如图所示,它在第一次评估中不可见,但在第二次评估中奇怪地可见。

❯ function foo() {
  echo "export FOO=BAR"
  echo "export CAR=$(echo $FOO)"
}

~
❯ eval $(foo)

~
❯ echo $CAR

~
❯ eval $(foo)

~
❯ echo $CAR
BAR

eval $(foo) 扩展为:

eval 'export FOO=BAR export CAR=$(echo $FOO)'

export 的效果是导致两个分配都被处理 'at the same time' 并且由于 FOO 在这行代码之前未知,因此第二个分配变为 CAR=$(echo '')=''.只有在第 2 个 eval $(foo)FOO 才有一个值,所以 CAR=BAR.

为了绕过这个副作用并获得 CAR=BAR(对于第一个 eval $(foo)),您可以删除 export 或让函数在两者之间打印 ;两个 exports(明确地将 exports 分开为两个单独的命令),例如:

# remove 'export'

foo() {
  echo "FOO=BAR"
  echo "CAR=$(echo $FOO)"
}

# explicitly separate into 2 commands via a ';'

foo() {
  echo "export FOO=BAR ;"                # notice the ';' appended on the end
  echo "export CAR=$(echo $FOO)"
}

对于第二个 foo() 定义,eval $(foo) 扩展为:

eval 'export FOO=BAR ; export CAR=$(echo $FOO)'

在我们 parse/execute CAR=$(echo $FOO).

之前用两个单独的命令 FOO 赋值

我们可以通过一个简化示例看到 export 的这种行为(没有 Gordon Davisson 的评论中提到的问题):

$ export A=3 B="$A"
$ typeset -p A B
declare -x A="3"
declare -x B=""              # A does not have a value so B=""

$ export A=3 B="$A"
$ typeset -p A B
declare -x A="3"
declare -x B="3"             # A now has a value (from 1st run) so B=3