如果您在原始脚本中运行子外壳程序:
(command1; command2; ...)
子 shell 是由 创建的原始 shell 的直接副本fork()
,因此可以直接访问它自己的所有可用原始变量的副本。
假设子 shell 中的命令(等)本身就是 shell 脚本command1
。command2
这些命令由子shell调用执行fork()
,然后exec()
创建一个新的shell,新的shell不会继承原始shell的非导出变量。
直接解决您的示例:
$ a=100
$ (echo $a)
100
$
在这里,子 shell 拥有a
父 shell 有权访问的所有变量(特别是 )的自己的副本。当然,在子 shell 中所做的任何更改都不会反映在父 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
,但主 shella
没有更改。然后当a
导出时,它可以b.sh
自动使用,因此它会看到并回显最后 100 个。