13.1.9 变量的作用域
变量的作用域又叫“命名空间”,表示变量(identifier,标识符)的上下文。相同的变量可以在多个命名空间中定义,并且彼此之间互不干涉,所以在一个新的命名空间中可以自定义任何变量,因为所定义的变量都只在各自的命名空间中。就像A班有个小明,B班也有个小明一样,虽然他们都叫小明(对应于变量名),但是由于所在的班级不一样(对应于命名空间),所以这不会造成混乱。但是如果同一个班级中有两个小明,就必须用类似于“大小明”、“小小明”这样的命名来区分他们。
在Linux系统中,不同进程ID的Shell默认为一个不同的命名空间。下面的例子展示了同名变量在两个不同命名空间中是互不影响的。
- #Namespace01.sh
中声明了VAR_01=100
[root@localhost ~]# cat Namespace01.sh
#!/bin/bash
VAR_01=100
echo VAR_01 in $0:$VAR_01
#
此处调用Namespace02.sh
bash Namespace02.sh
#Namespace02.sh
中声明了VAR_01=200
[root@localhost ~]# cat Namespace02.sh
#!/bin/bash
VAR_01=200
echo VAR_01 in $0:$VAR_01
#
执行Namespace01.sh
,看到同名变量VAR_01
在不同的脚本中的值是不一样的
[root@localhost ~]# bash Namespace01.sh
VAR_01 in Namespace01.sh:100
VAR_01 in Namespace02.sh:200
Shell变量的作用域是在本Shell内,属于本Shell的全局变量,也就是从定义该变量的地方开始到Shell结束,或到主动使用unset删除了该变量的地方为止。在变量的作用域内,该变量都是可见的,在函数内对变量也是可以访问、可修改的,这和C语言极为不同。
- [root@localhost ~]# cat Namespace03.sh
#!/bin/bash
VAR_02=100
#
定义函数ch_var()
,该函数中重新定义VAR_02
并赋值为200
function ch_var() {
VAR_02=200
}
echo "Before function VAR_02:$VAR_02"
#
调用函数
ch_var
echo "After function VAR_02:$VAR_02"
#Namespace03.sh
执行结果
[root@localhost ~]# bash Namespace03.sh
Brfore function VAR_02:100
After function VAR_02:200
同样的代码用C实现后,VAR_02的值并没有受到函数内部同名变量的影响。
- [root@localhost ~]# cat Namespace03.c
#include <stdio.h>
int VAR_02=100;
void ch_var(void) {
int VAR_02=200;
}
int main() {
printf("Before function VAR_02: %d\n", VAR_02);
ch_var();
printf("After function VAR_02: %d\n", VAR_02);
}
#
执行结果
[root@localhost ~]# ./a.out
Before function VAR_02: 100
After function VAR_02: 100
存在这种差别的原因在于,Shell默认以Shell的进程ID作为一个命名空间,所以即便是在函数中声明变量,该变量也会在全局生效。而C语言会对函数内的变量单独创建命名空间,这样就不会影响全局定义的同名变量。
Shell的这种特性在一般情况下是没有太大问题的,但有时确实可能会给程序的开发造成麻烦,特别是当脚本实现了模块化的开发后,不同的人共同维护同一个脚本中不同功能的代码时,很可能大家都会用到比较常见的类似于i、j、k这样的临时变量(特别是在函数内部,使用这样的变量尤为常见),这无疑会造成问题。为了解决这种问题,在函数内部声明的临时变量需要用local指定其为只在函数内生效的“局部变量”,这样这些变量将只存在于局部的命名空间内,从而不会对全局变量有影响。下面按照这种方式对Namespace03.sh进行修改,在函数内部使用local声明变量VAR_02,再次执行然后查看效果。
- [root@localhost ~]# cat Namespace03.sh
#!/bin/bash
VAR_02=100
function ch_var() {
local VAR_02=200 #
此处使用local
声明变量
}
echo "Before function VAR_02:$VAR_02"
ch_var
echo "After function VAR_02:$VAR_02"
#
修改后的Namespace03.sh
执行结果
[root@localhost ~]# bash Namespace03.sh
Before function VAR_02:100
After function VAR_02:100
从执行结果可以看到,在函数体内使用local关键字声明了和全局变量同名的局部变量后,对该变量的操作只会影响局部变量,而不会影响与之同名的全局变量。