bash shell 中变量的使用
简介
bash shell 中的变量就像脚本语言一样,可以直接拿来使用,并不需要提前声明。如果没有特殊的限定,则变量的默认类型是字符串。bash shell中的变量一共分为3类:
<1> 用户自定义的变量
也叫作本地变量,作用域为整个bash进程。
<2> 环境变量
使用export声明或者定义的变量。作用域为当前的shell进程以及子进程,不影响父进程。并且如果把环境变量写入对应的配置文件,则会对所有的shell生效。如/etc/profile, ~/.bashrc等。
用户可以使用export把变量声明为环境变量,比如 export name="Frogjie"。
系统也定义了一些环境变量,常见的有以下几个:
PATH 系统查找命令的路径
USER 当前登录的用户
HOSTNAME 主机名
SHELL 当前shell,一般是/bin/bash
<3> 位置变量
常用于函数传参或者shell进程接收命令行参数。常使用的有以下几种:
$0: 脚本的名字
$1, $2.... : 第n个参数。这里要注意的是,第10个参数应该写成${10}, 而不是直接用$10
<4> 特殊变量
$? 上一个命令的状态码或者函数的返回值(必须为整数)。如果是0,则表明程序执行正确。如果是非0,则表明执行出错。
$*, $@ 都表示当前shell的所有参数。这两个变量只有被双引号包围时才有区别。$*把所有参数当成一个整体。如果循环输出,只会输出一次。但是$@会把每个参数区分对待,循环输出会输出多次
$# 所有参数的个数
$$ 当前的进程号
变量的作用域
bash shell 中变量的作用域和一般的语言不太一样。比如在函数体内定义的变量默认是global变量,函数体外可以被访问到!!!
<1> shell脚本内定义的变量是global变量,作用域从定义的地方开始,到被显示删除或者shell结束。比如下面的代码,
输出这样的结果:
因为global变量的作用域是从定义处开始的,当函数fun执行时,global的name变量已经定义完成。所以在fun函数内部可以访问到。由于name是global的,所以fun函数对其进行改变,在fun函数外部也是可以感知的到的。
<2> 函数内部定义的变量默认也是global的,它的作用域是从函数被调用中执行变量定义的地方开始,到显示被删除或者shell结束为止。有点不好懂,看代码:
输出如下结果:
脚本中第一个name没输出的原因是,fun函数还没有开始执行,所以global name 变量还没有定义,所以没有输出。第二个fun中的name没有输出是因为虽然fun函数开始执行了,但是输出name的操作在定义global name之前,所以也没有输出。在fun函数执行完之后,由于函数内部定义的变量也是global的,所以正确输出了。
这样的作用域对于使用习惯高级语言的人来说,总是感觉怪怪的。bash shell提供了local关键字。对于上述的代码,如果函数内部的变量不想让外部访问到,则可以这样: local name="Frogjie"
<3> 当局部变量和全局变量冲突时,这个和其他高级语言是一样的,局部变量将会暂时覆盖全局变量。出了局部变量的作用域后,程序使用的是全局变量。
dclare的使用
dclare语法是这样的:
declare [+-][afrix]
"+/-" 用来指定变量的属性,“-”用来指定变量的属性,“+”用来取消变量的属性。但是有两个例外,不能用+a来销毁数组变量,不能用+r来取消变量read_only属性。
"-a" 指定变量为数组
"-i" 指定变量为整数
“-r” 指定变量只读
"-l" 如果设置了这个属性,赋值给此变量的字符串中的大写字母将会全部被转换成小写字母
"-u" 如果设置了这个属性,赋值给此变量的字符串中的小写字母将会全部被转换成大写字母
<1> 设置变量为只读
<2> 设置变量为整数
这个有一个很有趣的特性。如果设置某个变量为整数,那么可以直接把表达式赋值给它,它会直接把表达式的值计算出来。但是根据简单测试,只能传递简单的表达式,如果里面带有括号或者其他比较特殊的运算符就会出错。同时不能给它赋值浮点数。如果给一个整数变量赋值一个字符串,那么结果是0