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 中的相关问题。
在:
$(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_A
和export TEST_B=1
(同样,两个简单的命令)。