shell级别的变量范围

时间:2013-05-20 15:37:34

标签: linux bash shell

最近我一直在阅读The Advanced Bash Script,我在父母和子女之间找到了关于变量范围的东西,这让我非常困惑。这是:

场景: 有一些方法可以生成子shell: 首先,(command-lists); 第二,执行非内置命令或脚本,依此类推。

因为当我们在父脚本中运行脚本时,子脚本无法在父shell中看到变量。为什么在(command-lists)结构中,子shell可以看到父shell中的变量。 e.g

  1. (命令列表)

    $ a=100
    $ (echo $a)
    100
    $
    
  2. 运行脚本

    $ cat b.sh
    echo $a
    $ a=100
    $ ./b.sh
    # empty
    
  3. 如何?

1 个答案:

答案 0 :(得分:8)

如果您在原始脚本中运行了子shell:

(command1; command2; ...)

子shell是由fork()创建的原始shell的直接副本,因此可以直接访问其自己可用的所有原始变量的副本。

假设子shell中的命令(command1command2等)本身就是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个。