1.创建变量
用户创建变量的时候,变量名必须遵守下面的规则。
- 字母、数字和下划线字符组成。
- 第一个字符必须是一个字母或一个下划线,不能是数字。
- 不允许出现空格和标点符号。
变量声明的语法如下。
variable=value
上面命令中,等号左边是变量名,右边是变量。注意,等号两边不能有空格。
如果变量的值包含空格,则必须将值放在引号中。
myvar="hello world"
Bash 没有数据类型的概念,所有的变量值都是字符串。
下面是一些自定义变量的例子。
a=z # 变量 a 赋值为字符串 z b="a string" # 变量值包含空格,就必须放在引号里面 c="a string and $b" # 变量值可以引用其他变量的值 d="\t\ta string\n" # 变量值可以使用转义字符 e=$(ls -l foo.txt) # 变量值可以是命令的执行结果 f=$((5 * 7)) # 变量值可以是数学运算的结果
变量可以重复赋值,后面的赋值会覆盖前面的赋值。
$ foo=1 $ foo=2 $ echo $foo 2
上面例子中,变量
foo
的第二次赋值会覆盖第一次赋值。如果同一行定义多个变量,必须使用分号(
;
)分隔。$ foo=1;bar=2
上面例子中,同一行定义了
foo
和bar
两个变量。2.读取变量
读取变量的时候,直接在变量名前加上
$
就可以了。$ foo=bar $ echo $foo bar
每当 Shell 看到以
$
开头的单词时,就会尝试读取这个变量名对应的值。如果变量不存在,Bash 不会报错,而会输出空字符。
由于
$
在 Bash 中有特殊含义,把它当作美元符号使用时,一定要非常小心,$ echo The total is $100.00 The total is 00.00
上面命令的原意是输入
$100
,但是 Bash 将$1
解释成了变量,该变量为空,因此输入就变成了00.00
。所以,如果要使用$
的原义,需要在$
前面放上反斜杠,进行转义。$ echo The total is \$100.00 The total is $100.00
读取变量的时候,变量名也可以使用花括号
{}
包围,比如$a
也可以写成${a}
。这种写法可以用于变量名与其他字符连用的情况。$ a=foo $ echo $a_file $ echo ${a}_file foo_file
上面代码中,变量名
a_file
不会有任何输出,因为 Bash 将其整个解释为变量,而这个变量是不存在的。只有用花括号区分$a
,Bash 才能正确解读。事实上,读取变量的语法
$foo
,可以看作是${foo}
的简写形式。如果变量的值本身也是变量,可以使用
${!varname}
的语法,读取最终的值。$ myvar=USER $ echo ${!myvar} ruanyf
上面的例子中,变量
myvar
的值是USER
,${!myvar}
的写法将其展开成最终的值。如果变量值包含连续空格(或制表符和换行符),最好放在双引号里面读取。
$ a="1 2 3" $ echo $a 1 2 3 $ echo "$a" 1 2 3
上面示例中,变量
a
的值包含两个连续空格。如果直接读取,Shell 会将连续空格合并成一个。只有放在双引号里面读取,才能保持原来的格式。3.删除变量
unset
命令用来删除一个变量。unset NAME
这个命令不是很有用。因为不存在的 Bash 变量一律等于空字符串,所以即使
unset
命令删除了变量,还是可以读取这个变量,值为空字符串。所以,删除一个变量,也可以将这个变量设成空字符串。
$ foo='' $ foo=
上面两种写法,都是删除了变量
foo
。由于不存在的值默认为空字符串,所以后一种写法可以在等号右边不写任何值。4.输出变量,export 命令
用户创建的变量仅可用于当前 Shell,子 Shell 默认读取不到父 Shell 定义的变量。为了把变量传递给子 Shell,需要使用
export
命令。这样输出的变量,对于子 Shell 来说就是环境变量。export
命令用来向子 Shell 输出变量。NAME=foo export NAME
上面命令输出了变量
NAME
。变量的赋值和输出也可以在一个步骤中完成。export NAME=value
上面命令执行后,当前 Shell 及随后新建的子 Shell,都可以读取变量
$NAME
。子 Shell 如果修改继承的变量,不会影响父 Shell。
# 输出变量 $foo $ export foo=bar # 新建子 Shell $ bash # 读取 $foo $ echo $foo bar # 修改继承的变量 $ foo=baz # 退出子 Shell $ exit # 读取 $foo $ echo $foo bar
上面例子中,子 Shell 修改了继承的变量
$foo
,对父 Shell 没有影响。5.特殊变量
Bash 提供一些特殊变量。这些变量的值由 Shell 提供,用户不能进行赋值。
5.1 $?
$?
为上一个命令的退出码,用来判断上一个命令是否执行成功。返回值是0
,表示上一个命令执行成功;如果不是零,表示上一个命令执行失败。$ ls doesnotexist ls: doesnotexist: No such file or directory $ echo $? 1
上面例子中,
ls
命令查看一个不存在的文件,导致报错。$?
为1,表示上一个命令执行失败。5.2 $$
$$
为当前 Shell 的进程 ID。$ echo $$ 10662
这个特殊变量可以用来命名临时文件。
LOGFILE=/tmp/output_log.$$
5.3 $_
$_
为上一个命令的最后一个参数。$ grep dictionary /usr/share/dict/words dictionary $ echo $_ /usr/share/dict/words
5.4 $!
$!
为最近一个后台执行的异步命令的进程 ID。$ firefox & [1] 11064 $ echo $! 11064
上面例子中,
firefox
是后台运行的命令,$!
返回该命令的进程 ID。5.5 $0
$0
为当前 Shell 的名称(在命令行直接执行时)或者脚本名(在脚本中执行时)。$ echo $0 bash
上面例子中,
$0
返回当前运行的是 Bash。5.6 $-
$-
为当前 Shell 的启动参数。$ echo $-
himBHs
5.7 [email protected]
和$#
$#
表示脚本的参数数量,[email protected]
表示脚本的参数值,参见脚本一章。6.变量的默认值
Bash 提供四个特殊语法,跟变量的默认值有关,目的是保证变量不为空。
${varname:-word}
上面语法的含义是,如果变量
varname
存在且不为空,则返回它的值,否则返回word
。它的目的是返回一个默认值,比如${count:-0}
表示变量count
不存在时返回0
。${varname:=word}
上面语法的含义是,如果变量
varname
存在且不为空,则返回它的值,否则将它设为word
,并且返回word
。它的目的是设置变量的默认值,比如${count:=0}
表示变量count
不存在时返回0
,且将count
设为0
。${varname:+word}
上面语法的含义是,如果变量名存在且不为空,则返回
word
,否则返回空值。它的目的是测试变量是否存在,比如${count:+1}
表示变量count
存在时返回1
(表示true
),否则返回空值。${varname:?message}
上面语法的含义是,如果变量
varname
存在且不为空,则返回它的值,否则打印出varname: message
,并中断脚本的执行。如果省略了message
,则输出默认的信息“parameter null or not set.”。它的目的是防止变量未定义,比如${count:?"undefined!"}
表示变量count
未定义时就中断执行,抛出错误,返回给定的报错信息undefined!
。上面四种语法如果用在脚本中,变量名的部分可以用数字
1
到9
,表示脚本的参数。filename=${1:?"filename missing."}
上面代码出现在脚本中,
1
表示脚本的第一个参数。如果该参数不存在,就退出脚本并报错。