bash变量的作用域
bash变量的作用域
bash有两类变量:全局变量和函数内变量
全局变量
定义在函数外面的函数就是全局变量。
下面例子定义和使用了一个全局变量MYVAR。
#!/bin/bash
MYVAR="aaa"
echo $MYVAR
函数内使用全局变量
#!/bin/bash
function foo() {
echo $MYVAR
}
MYVAR="aaa"
foo
echo $MYVAR
注意:
- bash变量不需要事先定义,一条赋值语句就会定义变量,规则如下:
- 在当前作用域内查询变量是否已经存在,如果存在就给变量赋值。
- 如果不存在,则在当前作用域内定义该变量。
函数内变量
函数内定义变量必须使用typeset关键字。
case 1:如果没有使用typeset关键字
那么这个变量就是一个全局变量,bash会把他定义在全局作用域了。
#!/bin/bash
function foo() {
MYVAR="aaa"
}
echo "1="$MYVAR
foo
echo "2="$MYVAR
运行结果:
1=
2=aaa
在"1"的时候全局域MYVAR还没有定义,所以为空。
在"2"的时候全局域MYVAR已经在foo内被定义了,所以打印出"aaa"。
case 2: 使用typeset关键字
还是上面的例子,只是引用了关键字typesest。
#!/bin/bash
function foo() {
typeset MYVAR="aaa"
}
echo "1="$MYVAR
foo
echo "2="$MYVAR
运行结果:
1=
2=
可见函数内定义的变量,并没有反应到函数外面。
一个思考,在函数外定义变量是否需要typeset,其实是不需要的,有没有typeset关键字效果一样。但是有些时候需要给变量指定类型的时候,可以使用typeset表明类型,例如浮点数,或者数组变量等。
文件域变量
熟悉C语言的人,经常会问这个问题。
回答是:bash没有文件域变量。只有上述两种。
导出变量(export)
- 一个变量没有导出,那么说明只在当前进程有效
- 一个变量如果导出,则在子进程中也可见。
- 函数内部变量导出,那么这个变量就不再是函数内变量了,而是一个导出变量。
case 1: 函数内导出变量
#!/bin/bash
function foo() {
export MYVAR="aaa"
}
echo "1="$MYVAR
foo
echo "2="$MYVAR
运行结果:
1=
2=aaa
这个MYVAR已经是一个全局变量了;当然你可以试试下面这种语法:
$ cat main.sh
#!/bin/bash
function foo() {
typeset export MYVAR1="aaa"
export typeset MYVAR2="bbb"
}
foo
echo "1="$MYVAR1
echo "2="$MYVAR2
$ main.sh
1=
2=bbb
MYVAR1没有打出来;注意在实际项目中,我们一般不这么用的 :-)。
case 2: 导出变量用法
看一个例子:
#!/bin/bash
MYVAR1="111"
export MYVAR2="222"
function foo() {
MYVAR3="333"
export MYVAR4="444"
typeset MYVAR5="555"
}
foo
echo "m1="$MYVAR1
echo "m2="$MYVAR2
echo "m3="$MYVAR3
echo "m4="$MYVAR4
echo "m5="$MYVAR5
./sub.sh
看sub.sh
#!/bin/bash
echo "s1="$MYVAR1
echo "s2="$MYVAR2
echo "s3="$MYVAR3
echo "s4="$MYVAR4
echo "s5="$MYVAR5
运行结果:
m1=111
m2=222
m3=333
m4=444
m5=
s1=
s2=222
s3=
s4=444
s5=
我们看到在main.sh里面除了VAR5(函数内typeset定义)其他都是可见的,而在sub.sh里面只有VAR2和VAR4可见,因为它两在main.sh里面导出(export)了。
当在bash里面调用另一个脚本的时候,实际上是发起另一个进程,和调用者不在一个进程空间里面。如果非要求在同一个进程空间里面,可以使用点号(.),或者source语法。
再运行上面的例子,使用source sub.sh
#!/bin/bash
MYVAR1="111"
export MYVAR2="222"
function foo() {
MYVAR3="333"
export MYVAR4="444"
typeset MYVAR5="555"
}
foo
echo "m1="$MYVAR1
echo "m2="$MYVAR2
echo "m3="$MYVAR3
echo "m4="$MYVAR4
echo "m5="$MYVAR5
source ./sub.sh
这次运行的结果是:
m1=111
m2=222
m3=333
m4=444
m5=
s1=111
s2=222
s3=333
s4=444
s5=
sub.sh的结果和main.sh的结果一模一样,因为sub.sh和main.sh在同一个进程空间里面了。