【发布时间】:2015-11-21 10:45:46
【问题描述】:
这就是在 subshell 环境中执行命令时发生的情况:
该命令将在当前shell execution environment的副本中运行
“影响 shell 环境的变量分配和内置命令在命令完成后不会保持有效” (quote)
例子:
#!/bin/sh
export TOTO=123
FOO=abc
(mycmd)
在这种情况下,mycmd 将能够读取 TOTO 而不是 FOO,并且 mycmd 对这两个变量的值所做的每一次更改都不会在当前 shell 中可见。
但是当我们对一个函数做同样的事情时会发生什么呢?
例子:
#!/bin/sh
export TOTO=123
FOO=abc
function (){
echo $TOTO
echo $FOO
TOTO=${TOTO}456
FOO=${FOO}def
}
(function)
echo $TOTO
echo $FOO
结果:
123
abc
123
abc
合理地,在子 shell 中执行的函数无法更改父 shell 中定义的变量的内容,另一方面,它能够不加选择地读取所有变量,即使它们没有被导出。
有人可以用更好的方式解释这种行为吗? 非常感谢一些参考的链接,因为我找不到任何关于它的内容。
【问题讨论】:
-
谢谢。我知道这一点,但我想了解的是为什么在子 shell 中执行的函数能够读取所有变量,即使它们没有被导出。
-
当你在子shell中调用函数时,函数及其变量在子shell中执行,现在我看到你的问题——同样的规则——子shell可以访问
TOTO和@ 987654327@ 是函数范围,如果在该子 shell 中执行,则不应影响脚本主体中声明的TOTO和FOO的现有值。即使没有重新声明,由于 subshell 继承了 parent 的环境,同样的结果也会适用。 -
所以每当一个函数在子shell中执行时,它会接收到其作用域的所有变量?有没有办法避免它并像普通命令一样执行它?
-
是的 - 连同父环境的副本(包括变量),但函数可以重新声明变量,就像您所做的那样。如果你没有在函数中重新声明变量,那么当不在子shell中运行时,它会修改主体中的变量,但是当在子shell中运行时,它会被阻止修改父环境中的任何东西——包括变量。 (现在它仍然可以
return一个整数值)。 -
另请注意,子shell 对于它们继承的环境有自己的规则,与它们是否在新进程中执行无关(它们通常但不是必须这样做):将
echo $$ $BASHPID与(echo $$ $BASHPID)在 bash 4 或更高版本中。