最近一直在看The Advanced Bash Script我发现一些关于父 shell 和子 shell 之间的变量范围 的事情让我非常困惑。在这里:
场景:
有一些方法可以生成子 shell:
首先,(command-lists)
;
其次,执行非内置命令或脚本等。
因为当我们在父脚本中运行脚本时,子脚本无法看到父 shell 中的变量。为什么在 (command-lists)
结构中子 shell 可以看到父 shell 中的变量。
例如
(命令列表)
$ a=100 $ (echo $a) 100 $
运行脚本
$ cat b.sh echo $a $ a=100 $ ./b.sh # empty
如何?
最佳答案
如果您在原始脚本中运行子 shell:
(command1; command2; ...)
子 shell 是由 fork()
创建的原始 shell 的直接副本,因此可以直接访问它自己可用的所有原始变量的副本。
假设子 shell 中的命令(command1
、command2
等)本身就是 shell 脚本。这些命令由子shell执行调用fork()
然后exec()
创建一个新的shell,新的shell不继承非导出变量来自原始 shell 。
直接解决您的示例:
$ a=100
$ (echo $a)
100
$
在这里,子 shell 拥有父 shell 可以访问的所有变量(具体来说,a
)的副本。当然,在子 shell 中所做的任何更改都不会反射(reflect)在父 shell 中,因此:
$ a=100
$ (echo $a; a=200; echo $a)
100
200
$ echo $a
100
$
现在你的第二个例子:
$ cat b.sh
echo $a
$ a=100
$ ./b.sh
$ . ./b.sh
100
$ source ./b.sh
100
$ a=200 ./b.sh
200
$ echo $a
100
$ export a
$ ./b.sh
100
$
变量a
没有导出,所以第一次运行b.sh
时,$a
没有值所以它回显一个空行。后两个例子是“作弊”; shell 读取脚本 b.sh
就好像它是当前 shell 的一部分(没有 fork()
)所以变量仍然可以被 b.sh 访问
,因此它每次都回显 100。 (点或 .
是在当前 shell 中读取脚本的旧机制;第 7 版 UNIX 中的 Bourne shell 使用它。source
命令是从 C shell 借来的作为等效机制。)
命令 a=200 ./b.sh
在命令执行期间输出 a
,所以 b.sh
看到并回显修改后的值 200
但主 shell 的 a
没有变化。然后,当 a
被导出时,它自动可供 b.sh
使用,因此它会看到并回显最后的 100。
关于linux - shell 级别的变量范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16653069/