最近我一直在阅读The Advanced Bash Script,我在父母和子女之间找到了关于变量范围的东西,这让我非常困惑。这是:
场景:
有一些方法可以生成子shell:
首先,(command-lists)
;
第二,执行非内置命令或脚本,依此类推。
因为当我们在父脚本中运行脚本时,子脚本无法在父shell中看到变量。为什么在(command-lists)
结构中,子shell可以看到父shell中的变量。
e.g
(命令列表)
$ a=100
$ (echo $a)
100
$
运行脚本
$ cat b.sh
echo $a
$ a=100
$ ./b.sh
# empty
如何?
答案 0 :(得分:8)
如果您在原始脚本中运行了子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中所做的任何更改都不会反映在父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。 (Dot或.
是用于在当前shell中读取脚本的旧机制;第7版UNIX中的Bourne shell使用它。source
命令是从C shell中借用的等效机制。)
命令a=200 ./b.sh
在命令持续时间内导出a
,因此b.sh
会看到并回显修改后的值200
,但主shell有a
不变。然后,当导出a
时,b.sh
会自动将其显示,因此它会查看并回显最后100个。