Bash:具有多个未设置/导出命令的命令替换

sko*_*zin 4 bash command-substitution

我正在尝试取消设置一些变量并使用命令替换导出其他变量。这有效:

$(echo "
    export TEST_A=1
    export TEST_B=2
")
Run Code Online (Sandbox Code Playgroud)

这也是:

$(echo "
    unset TEST_A
    unset TEST_B
")
Run Code Online (Sandbox Code Playgroud)

但是,这在 OSX 和 Debian Jessie 上的 Bash 4.3.30(1)-release 失败:

$(echo "
    unset TEST_A
    export TEST_B=1
")
# bash: unset: `TEST_B=1': not a valid identifier
Run Code Online (Sandbox Code Playgroud)

这是预期的行为,如何使用命令替换取消设置和导出多个变量?

提供一些上下文:这是boot2docker 中的相关问题

Sté*_*las 7

在:

$(echo "
  export TEST_A=1
  export TEST_B=2
")
Run Code Online (Sandbox Code Playgroud)

$(...),只有一个扩展被解析为一个简单的命令。

所以这个$(...)扩展经历了 split+glob 运算符。的输出echo被修剪掉其尾随换行符,并在 IFS 字符上拆分为几个单词(默认为换行符、空格和制表符):

  • export
  • TEST_A=1
  • export
  • TEST_B=2

并且每个词都经历了globbing。在这里它们扩展到自己,因为它们不包含通配符。所以在 globbing 之后,我们仍然有相同的四个字符串列表。

要运行的命令源自第一个。这里export和所有这些字符串都作为参数传递给该命令。所以,在这里,就好像你写了:

export TEST_A=1 export TEST_B=2
Run Code Online (Sandbox Code Playgroud)

因此,您要导出TEST_A值为 1 的export变量、不更改其值的TEST_B变量和值为 2的变量。

在最后一个中,您正在运行:

unset TEST_A export TEST_B=1
Run Code Online (Sandbox Code Playgroud)

如果您希望将 的输出echo视为要解释的 shell 代码,那么这就是您要使用eval 不是使用split+glob运算符的地方(引用您的命令替换):

eval "$(echo "
  unset TEST_A
  export TEST_B=1
")"
Run Code Online (Sandbox Code Playgroud)

那也是一个简单的命令。两个字符串:eval<newline><spaces>unset TEST_A<newline><spaces>export TEST_B=1

eval将其参数的内容作为 shell 代码进行评估。所以它运行这两个 shell 命令行:unset TEST_Aexport TEST_B=1(同样,两个简单的命令)。