通过本文能对shell变量有一个系统性的了解,具体的包括:
- 变量的种类:局部、全局、环境变量
- 变量的定义和操作:赋值、取值、取消变量
- 变量的作用域
变量指向一片用于存储数据的内存空间。
shell变量是一种弱类型的变量,即在声明变量时不需要指定其类型。
所谓全局变量,就是指变量在当前的整个 Shell 进程中都有效。每个 Shell 进程都有自己的作用域,彼此之间互不影响。在 Shell 中定义的变量,默认就是全局变量。
需要强调的是,全局变量的作用范围是当前的 Shell 进程,而不是当前的 Shell 脚本文件,它们是不同的概念。
打开一个 Shell 窗口就创建了一个 Shell 进程,打开多个 Shell 窗口就创建了多个 Shell 进程,每个 Shell 进程都是独立的,拥有不同的进程 ID。在一个 Shell 进程中可以使用 source 命令执行多个 Shell 脚本文件,此时全局变量在这些脚本文件中都有效。
打开一个 Shell 窗口,输入以下命令:
[c.biancheng.net]$ a=99
[c.biancheng.net]$ . ./a.sh
99
[c.biancheng.net]$ . ./b.sh
200
这三条命令都是在一个进程中执行的,从输出结果可以发现,在 Shell 窗口中以命令行的形式定义的变量 a,在 a.sh 中有效;在 a.sh 中定义的变量 b,在 b.sh 中也有效,变量 b 的作用范围已经超越了 a.sh。
默认情况下:
Shell 函数中定义的变量默认是全局变量,它和在函数外部定义变量拥有一样的效果。
如下shell 列子:
#!/bin/bash
#定义函数
function func(){
a=99
}
#调用函数
func
#输出函数内部的变量
echo $a
执行shell
99
通过关键字 local 可以声明变量仅在函数中生效
#!/bin/bash
#定义函数
function func(){
local a=99
}
#调用函数
func
#输出函数内部的变量
echo $a
输出结果为空,表明变量 a 在函数外部无效,是一个局部变量。
全局变量只在当前 Shell 进程中有效,对其它 Shell 进程和子进程都无效。
如果使用export命令将全局变量导出,那么它就在所有的子进程中也有效了,这称为“环境变量”。
父子shell与环境变量的继承:
环境变量被创建时所处的 Shell 进程称为父进程,如果在父进程中再创建一个新的进程来执行 Shell 命令,那么这个新的进程被称作Shell 子进程。
当 Shell 子进程产生时,它会继承父进程的环境变量为自己所用,所以说环境变量可从父进程传给子进程。
环境变量与父子shell
[c.biancheng.net]$ a=22 #定义一个全局变量
[c.biancheng.net]$ echo $a #在当前Shell中输出a,成功
22
##进入shell子进程 ing
[c.biancheng.net]$ bash #进入Shell子进程
[c.biancheng.net]$ echo $a #在子进程中输出a,失败
[c.biancheng.net]$ exit #退出Shell子进程,返回上一级Shell
exit
#将a导出为环境变量 子进程可以查到
[c.biancheng.net]$ export a
[c.biancheng.net]$ bash #重新进入Shell子进程
[c.biancheng.net]$ echo $a #在子进程中再次输出a,成功
22
# 通过exit命令可以一层一层地退出 Shell。
[c.biancheng.net]$ exit #退出Shell子进程
exit
[c.biancheng.net]$ exit #退出父进程,结束整个Shell会话
注意:如果通过终端创建了一个新的 Shell 窗口,那它就不是当前 Shell 的子进程,环境变量对这个新的 Shell 进程是无效的。
bash-3.2$ ECHO $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public
#(重设)添加路径到PATH
# 仅对当前shell有效
bash-3.2$ export PATH=/somepath/path:$PATH
bash-3.2$ echo $PATH
/somepath/path:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public
shell中的变量必须以字母或者下划线开始,变量是区分大小写的
- 变量名和变量值之间没有空格
- 当变量值有空格时必须使用引号括起
gaoliang@MacBook-Pro demo % name=joho
gaoliang@MacBook-Pro demo % name1="$name"
gaoliang@MacBook-Pro demo % echo $name1
joho
gaoliang@MacBook-Pro demo % name1='$name'
gaoliang@MacBook-Pro demo % echo $name1
$name
取消变量是将变量从内存中释放,使用unset可以实现。
gaoliang@MacBook-Pro demo % unset Var
gaoliang@MacBook-Pro demo % echo $Var
Shell变量的作用域:
- 从定义该变量的地方开始到shell结束
- 或是主动使用unset删除该变量的地方为止
[root@tbds-10-1-0-38 log]# cat nameSpace2.sh
#!/bin/bash
echo before func Var1 is $0:$Var1
Var1=200
# 定义函数
function fun1(){
Var1=121
}
echo before func Var1 is $0:$Var1
#执行函数
fun1
echo after func Var1 is $0:$Var1
[root@tbds-10-1-0-38 log]# bash nameSpace2.sh
before func Var1 is run_quan.sh:
before func Var1 is run_quan.sh:200
after func Var1 is run_quan.sh:121
全局变量只在当前shell有效,如下例子:
[root@tbds-10-1-0-38 log]# cat nameSpace1.sh
#!/bin/bash
Var1=100
echo var1 is $0:$Var1
#调用bash
bash nameSpace2.sh
[root@tbds-10-1-0-38 log]# cat nameSpace2.sh
#!/bin/bash
# nameSpace1的Var1仅在自己的shell脚本中有效,
Var1=200
echo Var1 is $0:$Var1
[root@tbds-10-1-0-38 log]# bash nameSpace1.sh
var1 is nameSpace1.sh:100
Var1 is nameSpace2.sh:200
添加local指定局部变量
[root@tbds-10-1-0-38 log]# cat nameSpace2.sh
#!/bin/bash
Var1=200
function fun1(){
local Var1=121
}
echo before func Var1 is $0:$Var1
fun1
echo after func Var1 is $0:$Var1
#因为局部变量只在函数中起作用,所以执行完函数之后,输出的值还是全局变量
[root@tbds-10-1-0-38 log]# bash nameSpace2.sh
before func Var1 is nameSpace2.sh:200
after func Var1 is nameSpace2.sh:200