Shell变量的作用域

Shell变量的作用域(Scope), 就是Shell变量的有效范围(可以使用的范围).

在不同的作用于中, 同名的变量不会相互干涉.

Shell变量的作用域可以分为三种:

  • 有的变量只能在函数内部使用, 这叫做局部变量(local variable);
  • 有的变量可以在当前Shell进程中使用, 这叫做全局变量(global variable);
  • 有的变量还可以在子进程中使用, 这叫做环境变量(environment variable).

Shell局部变量

Shell也支持定义函数, 但是Shell函数和C++等其它编程语言函数的一个不同点就是: 在Shell函数中定义的变量默认也是全局变量, 它和在函数外部定义变量拥有一样的效果.

Example:

#/usr/bin/env bash

# 定义函数
function func()
{
    a=100
}

# 调用函数
func

# 输出函数内部的变量
echo $a

# 输出100
# a是在函数内部定义的, 但是在函数外部也可以得到它的值
# 证明它的作用域是全局的, 而不是仅限于函数内部

要想变量的作用域仅限于函数内部, 可以在定义时加上local关键字, 此时该变量就成了局部变量.

Example:

#!/usr/bin/env bash

# 定义函数
function func()
{
    local a=100
}

# 调用函数
func

# 输出函数内部的变量
echo $a

# 输出结果为空, 表明变量a在函数外部无效, 是一个局部变量.

Shell全局变量

所谓全局变量, 就是指变量在当前的整个Shell进程中都有效. 每个Shell进程都有自己的作用域, 彼此之间互不影响. 在Shell中定义的变量, 默认就是全局变量.

Shell环境变量

全局变量只在当前Shell进程中有效, 对其它的Shell进程和子进程都无效. 如果使用export命令将全局变量导出, 那么它就在所有的子进程中也有效了, 这称为环境变量.

环境变量被创建时所处的Shell进程称为父进程, 如果在父进程中再创建一个新的进程来执行Shell命令, 那么这个新的进程被称作Shell子进程. 当Shell子进程产生时, 它会继承父进程的环境变量, 所以环境变量可以从父进程传递给子进程.

注意, 两个没有父子关系的Shell进程是不能传递环境变量的, 并且环境变量只能向下传递而不能向上传递.

创建Shell子进程最简单的方式是运行bash命令, 通过exit命令可以一层一层地推出Shell.

Example:

a=22        # 定义一个全局变量
echo $a     # 在当前Shell中输出a, 成功

bash        # 进入Shell子进程
echo $a     # 在子进程中输出a, 失败

exit        # 退出Shell子进程, 返回上一级Shell

export a    # 将a导出为环境变量
bash        # 重新进入Shell子进程
echo $a     # 在子进程中再次输出a, 成功

exit        # 推出Shell子进程

exit        # 推出父进程, 结束整个Shell会话

export a这种形式是在定义变量之后再将它导出为环境变量, 如果想在定义的同时导出为环境变量, 可以写成export a=22.

环境变量也是临时的

通过export导出的环境变量只对当前Shell进程及其所有子进程有效, 如果最顶层的父进程被关闭了, 那么环境变量也就随之消失了, 其它的进程也就无法使用了, 所以说环境变量也是临时的.

如果想让一个变量在所有Shell进程中都有效, 不管它们之间是否存在父子关系, 该怎么办呢?

只有将变量写入Shell配置文件中才能达到这个目的. Shell进程每次启动时都会执行配置文件中的代码做一些初始化工作, 如果将变量放在配置文件中, 那么每次启动进程都会定义这个变量.