Bash 变量
变量定义
变量简单定义就是让某一个特定字符串代表不固定内容。
在 Bash 中变量分为环境变量和 shell 变量。
显示变量
可以使用 echo $变量名
来查看变量。将变量加上 {}
效果是一样的:
[root@101c7 4]$ echo {$PATH}
{/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin}
这个特性可以让字符串扩展变量。例如用 echo
显示 my ${rev}th version。
设置变量
直接用等号连接变量和内容就行了:
[root@101c7 4]$ myhome=ext333
[root@101c7 4]$ echo $myhome
ext333
使用 myhome='ext333'
的格式也能设置变量。通常变量值有带空格或特殊符号要这样设置。
注意等号两边如果有空格表示等量关系测试。
取消变量
使用 unset 变量名
取消变量设置:
[root@101c7 4]$ unset myhome
记住删除环境变量时,不用带 $
。所有使用变量时用 $
,操作变量不使用 $
。
变量设置规则
-
等号两边不能直接接空格符,变量内容有空格可使用双引号或单引号括起来。
-
变量名只能使用英文字母和数字。按照惯例,变量用全大写字母表示,不以数字开头。
-
双引号内特殊字符美元(
$
)、反引号(`)和反斜线(\
)可以保持原有特性,例如将 `` 撇号内的命令执行:
[root@101c7 4]$ varlan="lang is $LANG" ; echo $varlan
lang is en_US.UTF-8
- 单引号内特殊字符仅作为一般字符,因此也称单引号为强引用(Strong Quote),双引号为弱引用(Weak Quote)。
[root@101c7 4]$ varlang='lang is $LANG';echo $varlang
lang is $LANG
-
转义字符
\
将特殊符号(如$
、\
、空格、!
等)变成一般字符。 -
命令替换特性可以使用
命令
或$(命令)
来引用其他命令的 stdout:
[root@101c7 4]$ varlan=$(uname -r);echo $varlan
3.10.0-1160.41.1.el7.x86_64
- 变量增加内容可用
变量名称=$变量名称+新增内容
或变量=${变量}+新增内容
来给变量添加内容:
[root@101c7 4]$ PATH=${PATH}:/root
[root@101c7 4]$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root
- 若该变量需要在其他子程序执行,用
export
来使当前变量变成环境变量:
[root@101c7 4]$ export PATH
- 在子程序中修改全局环境变量并不会影响父 shell 中该变量的值,使用
export
也无效。 - 通常大写字符为系统默认环境变量,自行设置变量可以使用小写字符。
查看变量
要查看已定义的环境变量(全局变量),可以使用 env
或 export
命令:
[root@101c7 4]$ env
XDG_SESSION_ID=15
HOSTNAME=101c7
SELINUX_ROLE_REQUESTED=
TERM=vt100
SHELL=/bin/bash
要查看所有变量,包括自定义变量(局部变量),使用 set
命令:
[root@101c7 ~]$ set
XDG_SESSION_ID=15
_=16710
colors=/root/.dircolors
varlan=3.10.0-1160.41.1.el7.x86_64
varlang='lang is $LANG'
在 Bash 没有绝对的全局变量,环境变量即是全局变量又是局部变量。想要知道哪些是绝对的局部变量,只能比较 env
和 set
的输出。
获取变量长度
指取得变量字符串的长度,可以这样表示:
[root@server1 bin]$ echo ${#PATH}
59
PATH 变量
环境变量 PATH
定义了可执行文件目录。
如果不同目录中有相同名称文件,则按照先查询到的同名命令先被执行。
不同身份用户默认的 PATH
不同。
查看当前系统中 PATH
变量,显示结果每个目录中间用冒号 :
隔开,按照先后顺序排列:
[root@101c7 a1]$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
将 /root
目录加入到 $PATH
变量:
[root@101c7 a1]$ PATH="$PATH":/root ; echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root
数组变量
数组是能够储存多个值的变量,这些值可以单独引用,也可以作为整个数组来引用。
要设置环境变量,可以把值放到括号里,值与值之间用空格分隔:
[root@server1 ~]$ myarray=(one two)
使用 echo
直接变量只能读取第一个值,要引用一个单独的数组元素,必须使用索引值,从 0 开始索引:
[root@server1 ~]$ echo $myarray
one
[root@server1 ~]$ echo ${myarray[1]}
two
要显示整个数组变量,可以用星号或@作为通配符放在索引位置:
[root@server1 ~]$ echo ${myarray[*]}
one two
[root@server1 ~]$ echo ${arr[@]}
1,11,111
也可以直接修改某个索引位置的值:
[root@server1 ~]$ myarray[1]=1
[root@server1 ~]$ echo ${myarray[1]}
1
删除某个索引值位置的值用 unset
命令,它会清空对应索引值数据,但并不会重建索引:
[root@server1 ~]$ unset myarray[0]
[root@server1 ~]$ echo ${myarray[0]}
[root@server1 ~]$ echo ${myarray[*]}
1
对其他 shell 而言,数组变量可移植性不好,所以不常用到。
特殊变量
$$
代表 shell 的线程代号(PID),可以查询:
[root@101c7 ~]$ echo $$
17701
$?
代表上一个执行的命令所回传的值,成功执行返回 0,执行错误返回其他状态码:
[root@101c7 ~]$ 141=55
-bash: 141=55: command not found
[root@101c7 ~]$ echo $?
127
退出状态码一般通用参考如下:
状态码 | 描述 |
---|---|
0 | 命令成功结束 |
1 | 一般性未知错误 |
2 | 不适合的 shell 命令 |
126 | 命令不可执行 |
127 | 没找到命令 |
128 | 无效的退出参数 |
128+x | 与 Linux 信号 x 相关的严重错误 |
130 | 通过 Ctrl+C 终止的命令 |
255 | 正常范围之外的退出状态码 |
读取变量
要由用户输入来定义变量可以使用read
命令。
例如让用户在 30 秒内输入来自定义变量myname
:
[root@101c7 ~]$ read -p "type your name: " -t 30 myname
type your name: ass
[root@101c7 ~]$ echo $myname
ass
声明变量
declare
或typeset
可以用来声明变量,并支持定义变量类型。
可用参数为:
参数 | 说明 |
---|---|
-a | 将变量定义为数组(array)类型。 |
-i | 将变量定义为整数(integer)类型。 |
-x | 用法与 export 一样,将变量变成环境变量。 |
-r | 将变量设置为 readonly 类型,不能修改也不能取消。 |
例如让变量计算 1+2 的结果:
[root@101c7 ~]$ declare -i sum=1+2
[root@101c7 ~]$ echo $sum
3
将变量由环境变量变为非环境变量:
[root@101c7 ~]$ declare -r sum
[root@101c7 ~]$ declare -p sum
declare -air sum='([0]="3")'
定义数组变量 sum:
[root@101c7 ~]$ declare -a sum
[root@101c7 ~]$ sum[1]=111
[root@101c7 ~]$ sum[2]=222
[root@101c7 ~]$ echo ${sum[1]}
111
也可以不使用declare
提前声明。读取时必须使用${数组}
的方式读取。
变量内容修改
变量内容修改使用echo
设置,设置方式如下表:
变量设置方式 | 说明 |
---|---|
${变量#关键字} |
若变量内容从头开始的数据符合"关键字",则将符合的最少数据删除。 |
${变量##关键字} |
若变量内容从头开始的数据符合"关键字",则将符合的最多数据删除。 |
${变量%关键字} |
若变量内容从尾向前的数据符合"关键字",则将符合的最少数据删除。 |
${变量%%关键字} |
若变量内容从尾向前的数据符合"关键字",则将符合的最多数据删除。 |
${变量/旧字符串/新字符串} |
若变量内容符合"旧字符串",则第一个旧字符串会被新字符串替代。 |
${变量//旧字符串/新字符串} |
若变量内容符合"旧字符串",则全部的旧字符串会被新字符串替代。 |
例如删除变量中最后一个/root/bin
:
[root@101c7 ~]$ echo $myvar
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@101c7 ~]$ echo ${myvar%:*bin}
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
表示删除的是右数从 :
开始到 bin
结尾这一段内容。
尽可能多地删除变量从左数 /usr
开始到 local
结束之间的内容:
[root@101c7 ~]$ echo ${myvar##/usr*local}
/bin:/usr/sbin:/usr/bin:/root/bin
尽可能少地删除结果是这样:
[root@101c7 ~]$ echo ${myvar#/usr*local}
/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
设置变量默认值
当需要变量不存在时使用一个常用设置时,可以用 变量{变量-默认值}
来设置:
[root@101c7 ~]$ echo $myvar1
[root@101c7 ~]$ myvar1=${myvar1-root} ; echo $myvar1
root
[root@101c7 ~]$ myvar1=alice ; myvar1=${myvar1-root} ; echo $myvar1
alice
如果变量为空字符串无法辨别是否没有设置,这时用 变量{变量:-默认值}
来设置:
[root@101c7 ~]$ myvar1="" ; myvar1=${myvar1:-root} ; echo $myvar1
root
设置方法对比结果如下表:
设置方式 | str 没有设置 | str 为空字符串 | str 为非空字符串 |
---|---|---|---|
var=${str-expr} | var=expr | var= | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var= | var=expr | var=expr |
var=${str:+expr} | var= | var= | var=expr |
var=${str=expr} | str=expr,var=expr | str 不变,var= | str 不变,var=$str |
var=${str:=expr} | str=expr,var=expr | str=expr,var=expr | str 不变,var=$str |
var=${str?expr} | expr 输出至 stderr | var= | var=str |
var=${str:?expr} | expr 输出至 stderr | expr 输出至 stderr | var=str |