在各种Shell环境中都会用到变量的概念。Shell变量用来存放系统和用户需要使用的特定参数值,通过使用变量,Shell程序能够提供更加灵活的功能,适应性强。
常见的Shell变量的类型包括 系统变量,位置变量,预定义变量,自定义变量
下面围绕这四种变量类型来举例
系统变量
Linux中的环境变量是由系统定义的一些变量,主要用于设置用户的工作环境,包括宿主目录、命令查找路径、用户当前目录、登录终端等。环境变量的值由linux系统自动维护,会随着用户状态的改变而改变。
env
命令可以用来查看当前用户当前工作环境下的环境变量,可以试着用来查看一下,以下举出部分例子:
系统变量 | 变量含义 |
---|---|
$SHELL | 默认的 Shell 环境 |
$HOME | 当前用户宿主目录 |
$IFS | 内容字段分隔符,默认是空格 |
$LANG | 默认系统语言 |
$PWD | 当前所在目录 |
$UID | 当前用户ID |
$USER | 当前用户 |
$HISTSIZE | 历史命令大小 |
$RANDOM | 随机生成一个0~32767的整数 |
$HOSTNAME | 主机名 |
$PATH | 默认系统寻找的可执行命令路径 |
位置变量
位置变量也称为位置参数,使用$1 $2 $3 ...
,以执行命令为参照,从左到右的参数从$1
依次类推。如:ls -lh /root
,以ls为参照,-lh
为$1
,/root
为$2
,需要注意的是从第10个开始要用花括号调用,例如${10}。命令或者脚本本身用$0
表示,但$0
属于预定义变量,而不是位置变量。
例:
# 脚本示例
$ vi result.sh
#!/bin/bash
SUM=`expr $1 + $2`
echo "$1 + $2 = $SUM"
# 脚本赋权
$ chmod +x result.sh
# 执行脚本
$ ./result.sh 3 4
3 + 4 = 7
# 执行脚本过程中3为$1,4为$2
shift
命令可对位置变量进行控制,命令没执行一次,变量的个数会减 1,本身有 $1
和 $2
两个位置变量的情况下,执行一次 shift
后, $2
的值就变成了 $1
。如下所示
$ vim shift.sh
#!/bin/bash
echo "第一个参数为 $1"
echo "第二个参数为 $2"
echo "第三个参数为 $3"
echo "第一个参数为 $1"
shift
echo "第一个参数为 $1"
shift
echo "第一个参数为 $1"
$ sh shift.sh a b c
第一个参数为 a
第二个参数为 b
第三个参数为 c
第一个参数为 a
第一个参数为 b
第一个参数为 c
以上的例子可以看出,第一次输出abc时,$1=a,$2=b,$3=c,第二次输出abc时,$1=a,$1=b,$1=c,第二次输出完$1=a时,执行了一次 shift
,在输出$1,已经变成了b。说明在执行 shift
后,执行脚本变成了 shift.sh b c
,此时$1=b,以此类推,第二次执行 shift
后变成了 shift.sh c
,此时$1=c。
以上总结,shift
用来依次删除从左到右的位置变量
上面例子使用的 shift
,默认为 shift 1
,1也可以是其它整数,就变成了删除从左到右 n 个位置变量
预定义变量
预定义变量是由Bash程序预先定义好的一类特殊变量,用户只能使用预定义变量,而不能创建新的预定义变量,也不能为预定义变量赋值。
比较常用的如下:
$# | 表示命令行中位置参数的个数 |
$* | 表示所有位置参数的内容 |
$@ | 每个位置参数被看作独立的字符串 |
$? | 表示前一条命令执行后的状态,返回值为0表示执行正确,任何非0值均表示执行出现异常 |
$0 | 表示当前执行的脚本或程序的名称。 |
$$ | 当前进程PID |
$! | 上一条运行后台进程的PID |
例:
# 编写脚本
$ vi predefine.sh
#!/bin/bash
echo "该脚本为 $0 "
echo "该脚本一共使用了 $# 个参数"
echo "参数分别为 $* "
# 脚本授权
$ chmod +x predefine.sh
# 执行脚本
$ ./predefine.sh FeiYi \'s Blog
该脚本为 ./predefine.sh
该脚本一共使用了 3 个参数
参数分别为 FeiYi 's Blog
自定义变量
自定义变量是由系统用户自己定义的变量,只有用户在自己的Shell环境中有效,因此又称为本地变量。在编写Shell脚本程序时,通常会设置一些特定的自定义变量,以适应程序执行过程中的各种变量,满足不同的需求。
定义变量
Bash中的变量定义相对C、C++、Java等语言还是比较简单的,只需要使用等号即可进行变量的定义。
格式为:变量名=变量值
等号两边不能有空格。变量名须以字母或者下划线开头,名称中不能包含特殊字符(+、-、*、/、.、?、%、&、#等)。
例如要定义一个变量名为CYJ
,值为FeiYi
,一个变量名为PJF
,值为Blog
CYJ=FeiYi
PJF=Blog
查看和引用变量的值
通过在变量名前加“$”符号,可以引用变量的值。使用echo命令可以查看变量,可以在一条echo命令中同时查看多个变量值。
$ echo $CYJ $PJF
FeiYi Blog
当变量名容易和紧跟其后的字符相混淆时,需要添加大括号{}将变量名扩起来,否则将无法正确解析该变量的值,对于定义的变量显示空值。
$ echo $CYJBlog //变量值CYJBlog未定义
$ echo ${CYJ}Blog
FeiYiBlog
变量赋值的特殊操作
双引号(” “)
双引号主要起界定字符串的作用,特别是当复制的内容中包含空格时,必须以双引号引起来;其他情况双引号可以省略
$ MU=FeiYi Blog
bash: Blog: 未找到命令...
$ MU="FeiYi Blog"
$ echo $MU
FeiYi Blog
在双引号的范围内,使用$符号也可以引用其他变量的值,从而能够直接调用现有变量的值来赋给新的变量
$ MU="FeiYi $PJF"
$ echo $MU
FeiYi Blog
单引号(’ ‘)
当要赋值的内容中包含$、”、\等具有特殊含义的字符时,应该使用单引号引起来。在单引号范围内无法引用其他的变量值,任何字符都将看做普通字符。但赋值内容中包含单引号时,需要使用\进行转义,避免冲突
$ MU='FeiYi $PJF'
$ echo $MU
FeiYi $PJF
反撇号(``)
反撇号主要用于命令替换,允许将执行某个命令的屏幕输出结果赋值给变量。反撇号括起来的范围必须是能够执行的命令,否则将会出错。
$ ls -lh `which useradd`
-rwxr-x---. 1 root root 116K 11月 6 2016 /usr/sbin/useradd
这相当于执行了两条命令,先通过 which useradd
找到 useradd 命令所在的路径,在通过 ls -lh
查看该命令文件的详细信息
需要注意的是,使用反撇号难以在一行命令中实现嵌套命令替换操作,这时可以改用“$( )”来代替反撇号操作。
$ rpm -qc `rpm -qf `which useradd``
rpm:未给出要查询的参数
未安装软件包 useradd
$ rpm -qc $(rpm -qf `which useradd`)
/etc/default/useradd
/etc/login.defs
$ rpm -qc $(rpm -qf $(which useradd))
/etc/default/useradd
/etc/login.defs
read命令
-p:打印信息
-t:限定时间,-t5,5s内不输入就超时,退出read
-s:不回显。就像登录终端时,输入密码的时候不显示
-n:限制输入字符个数,-n6,只能输入6个字符
read是Bash的内置命令,也可以进行变量赋值。read主要可以用来提示用户输入信息,从而实现简单的交互过程。执行时将从标准输入设备(键盘)读取一行内容,并以空格为分隔符,将读入的个字段依次赋值给指定的变量(多余的内容赋给最后一个变量)。
$ read a b c
1 2 3 4 5 6 # 此部分是手动输入
$ echo $a
1
$ echo $b
2
$ echo $c
3 4 5 6
若指定变量只有一个,则将整行内容复制给此变量。
$ read a
1 2 3 4 5 6 # 此部分是手动输入
$ echo $a
1 2 3 4 5 6
为了使交互的方式更加的友好,提高易用性,read命令可以结合“-p”选项来设置提示信息,以便告知用户应该输入什么样的内容
$ read -p "请输入Yes或No:" a
请输入Yes或No:Yes
$ echo $a
Yes
变量状态赋值
主要用来判断变量是否为空
${VAR:-string} 如果VAR变量为空则返回string,不为空则返回变量值
${VAR:+string} 如果VAR变量不为空则返回string,为空则返回空
${VAR:=string} 如果VAR变量为空则重新赋值VAR变量值为string,不为空则返回变量值
${VAR:?string} 如果VAR变量为空则将string输出到stderr,不为空则返回变量值
设置变量的作用范围
默认情况下,新定义的变量只在当前的shell环境中有效,因此称为局部变量。当进入子程序或者新的shell环境时,局部变量将无法使用
$ echo $a
Yes
$ bash
$ echo $a
为了使用户定义的变量在所有的环境中都能够使用,减少重复设置的工作,可以通过内部命令export将指定的变量导出为全局变量。用户可以同时指定多个变量名作为参数,变量名之间以空格分隔,无需使用$引用变量
$ echo $CYJ $PJF
FeiYi Blog
$ export CYJ PJF
$ bash
$ echo $CYJ $PJF
FeiYi Blog
也可以直接使用export进行赋值,当然这么做的同时会定义变量和将变量变为全局变量
$ export a=5
$ bash
$ echo $a
5
shell输出格式化
echo:用于输出字符串的命令
选项:
-n:输出末尾不换行
-e:解释转义字符
$ echo -n "date: ";date +%F
date: 2021-04-06
shell中的转义字符
\a: 发出警告声。它确实是一段声音
# echo -e "\a"
\b: 删除前一个字符
###
for time in `seq 9 -1 0`; do
echo -n -e "$time\b"
sleep 1
done
###
\n和\r: 换行
\t: 插入tab
\v: 垂直制表,可结合\t使用
###
echo -e "name\tage\v\rFeiYi\t24"
name age
FeiYi 24
###
# 一些不常用的就不写了
字符串颜色
脚本中echo显示内容带颜色显示,echo显示带颜色,需要使用参数-e
格式:
# 末尾的0m也是属性效果的意思,如果修改末尾的会将你接下来所有的操作都和该属性效果一致
# 所以,要对特定字符串进行修改,属性效果写在前面就可以
echo -e "\033[底色;字体颜色 字符串\033[0m"
echo -e "\033[属性效果\033[底色;字体颜色 字符串\033[0m"
echo -e "\033[属性效果\033[字体颜色 字符串\033[0m"
# 底色不能单独使用,必须配合字体颜色使用
40-47
40:黑色
41:红色
42:绿色
43:黄色
44:蓝色
45:紫色
46:天蓝色
47:白色
30-37
30m:黑色
31m:红色
32m:绿色
33m:黄色
34m:蓝色
35m:紫色
36m:天蓝色
37m:白色
0m:关闭所有属性
1m:设置高亮度
4m:下划线
5m:闪烁
7m:反显
8m:消隐