shell级别的变量范围

Red*_* Lv 4 linux bash shell

最近我一直在阅读高级Bash脚本,我发现一些关于父壳和子壳之间的变量范围的东西让我非常困惑.这里是:

场景:有一些方法来生成一个子壳:第一,(command-lists); 第二,执行非内置命令或脚本,依此类推.

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

  1. (命令列表)

    $ a=100
    $ (echo $a)
    100
    $
    
    Run Code Online (Sandbox Code Playgroud)
  2. 运行一个脚本

    $ cat b.sh
    echo $a
    $ a=100
    $ ./b.sh
    # empty
    
    Run Code Online (Sandbox Code Playgroud)

怎么样?

Jon*_*ler 8

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

(command1; command2; ...)
Run Code Online (Sandbox Code Playgroud)

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

假设命令(command1,command2在副壳等)本身壳脚本.这些命令由子shell调用执行fork(),然后exec()创建一个新shell,新shell不会从原始shell继承未导出的变量.


直接解决您的示例:

$ a=100
$ (echo $a)
100
$
Run Code Online (Sandbox Code Playgroud)

在这里,子shell有自己的所有变量(具体地说a)是父shell可以访问的副本.当然,子shell中所做的任何更改都不会反映在父shell中,因此:

$ a=100
$ (echo $a; a=200; echo $a)
100
200
$ echo $a
100
$
Run Code Online (Sandbox Code Playgroud)

现在你的第二个例子:

$ 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
$
Run Code Online (Sandbox Code Playgroud)

该变量a未导出,因此第一次b.sh运行时,它没有值,$a因此它回显一个空行.第二个例子是'作弊'; shell读取脚本b.sh就好像它是当前shell的一部分(no 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个.