Shell脚本就是命令的集合,这也是脚本最简单易懂的理解。脚本的运行,无非就是想让命令在什么条件下怎么样的执行。如果仅仅是根据命令的集合来完成脚本自动化,就会出现很多的意外的脚本中断。要想让脚本有自己的”思想”。如:在创建目录之前,要知道有没有同名目录,如果同名的情况下,肯定会报错的。
在 Shell(二)—变量 一文中,预定义变量$?
,来判断命令执行后返回的状态值,返回0表示成功,非0值表示失败或异常。本文将介绍使用其它的方法来判断条件是否和预期的相同
条件表达式
使用test
命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值为0时,表示条件成立)。
命令格式
表达式 | 示例 |
---|---|
[ 条件表达式 ] | [ 1 -eq 1 ] |
[[ 条件表达式 ]] | [[ 1 -eq 1 ]] |
test 条件表达式 | test 1 -eq 1,等同于[ ] |
这三种方式作用相同,通常使用符号的形式,需要注意的是括号必须与表达式之间需要至少一个空格进行分隔。
根据测试的条件类别不同,条件表达式也不同。比较常用的条件操作包括文件测试、整数值比较、字符串比较、布尔运算以及针对多个条件的逻辑测试。
文件测试
文件测试指的是根据给定的路径名称,判断对应的是文件还是目录,或者判断文件是否可读、可写、可执行等。
文件测试常用的操作选项如下:
测试符 | 描述 | 示例 |
---|---|---|
-e | 判断文件或目录是否存在,存在为true | [ -e 文件或目录路径 ] |
-d | 判断目录是否存在,存在为true | [ -d 目录路径 ] |
-f | 判断文件是否存在,存在为true | [ -f 文件路径 ] |
-r | 判断文件是否有读取权限,有为true | [ -r 文件路径 ] |
-w | 判断文件是否有写入权限,有为true | [ -w 文件路径 ] |
-x | 判断文件是否有执行权限,有为true | [ -x 文件路径 ] |
-s | 判断文件是否存在且大小大于0,条件成立则为true | [ -s 文件路径 ] |
执行条件测试后,通过$?
可以获取测试命令的状态值,从而判断是否成立。例:
$ [ -d /media ]
$ echo $?
0
如果脚本中使用$?
来判断前一步的操作结果,略显笨拙,为了更直观的查看测试结果,可以结合命令分隔符 &&
和echo
一起使用。
&&
:表示只有当前面的命令执行成功后,才会执行符号后面的命令,反之不会执行后面的命令
echo
:放在&&
后面可以更直观的看到测试结果。
如:
$ [ -d /media/feiyi ] && echo "YES"
# 没有输出YES,表示目录不存在
整数值比较
整数值比较,顾名思义就是两个整数数字之间的比较,整数值比较的常用操作选项如下:
比较符 | 描述(条件成立则为true) | 示例(以下结果都为true) |
---|---|---|
-eq | 等于(Equal) | [ 1 -eq 1 ], 1等于1 |
-ne | 不等于(Not Equal) | [ 1 -ne 2 ], 1不等于2 |
-gt | 大于(Greater Than) | [ 2 -gt 1 ], 2大于1 |
-lt | 小于(Lesser Than) | [ 1 -lt 2 ], 1小于2 |
-ge | 大于等于(Greater Equal) | [ 2 -ge 1 ], 2大于等于1 |
-le | 小于等于(Lesser Equal) | [ 1 -le 2 ],1 小于等于2 |
整数值比较常用来判断登录用户数量、开启进程数、磁盘使用率是否超标,以及软件版本号是否符号要求。实际使用时,通常会用变量来引用、命令替换等方式来获取一个数值
如:判断当前登录用户数,超过5个时,输出Too Many
$ USERNUM=`who | wc -l`
$ [ $USERNUM -gt 5 ] && echo "Too Many"
Too Many
字符串比较
字符串比较,通常用来检查用户的输入,系统环境是否满足,在交互式脚本中,可以判断用户输入的位置参数是否符合要求。
字符串常用的操作选项如下:
比较符 | 描述(条件成立则为true) | 示例(以下结果都为true) |
---|---|---|
== | 等于 | [ “a” == “a” ] |
!= | 不等于 | [ “a” != “b” ] |
> | 大于(判断字符串时根据ASCII码表顺序,不常用) | [ 2 \> 1 ] [[ 2 > 1 ]] (( 2 > 1 )) |
< | 小于(判断字符串时根据ASCII码表顺序,不常用) | [ 1 \> 2 ] [[ 1 > 2 ]] (( 1 > 2 )) |
>= | 大于等于 | (( 2 >= 1 )) |
<= | 小于等于 | (( 1 <= 2 )) |
-n | 字符串长度不等于0 | a=1 [ -n “$a” ] |
-z | 字符串长度等于0 | b=”” [ -z “$b” ] |
如:判断系统使用语言
# 先查看系统使用的语言是什么
$ echo $LANG
en_US.UTF-8
$ [ $LANG != "en.US" ] && echo "Language is not en.US"
Language is not en.US
如:连同 read
使用
$ result="Yes"
$ [ $result == "Yes" ] && echo "是的"
是的
布尔运算符
运算符 | 描述 | 示例 |
---|---|---|
! | 条件取反 | [ ! 1 -eq 2 ] |
-a | 和(and) | [ 1 -eq 1 -a 2 -eq 2 ],必须同时满足两个条件 |
-o | 或(or) | [ 1 -eq 1 -o 2 -eq 1 ],只要有1个条件满足为true |
如:目录不存在则输出”/root/test existed”
$ [ ! -d /root/test ] && echo "/root/test existed"
如:两个条件全部成立则输出“nginx测试”,只要有一个不成立,则输出error
$ vim test.sh
#!/bin/bash
[ $1 == "test" -a $2 == "nginx" ] && echo "nginx测试" || echo "error"
$ sh test.sh test 2
error
$ sh test.sh test nginx
nginx测试
逻辑判断符
逻辑测试,指的是判断两个或多个条件之间的依赖关系
逻辑测试操作选项:
&&
:逻辑与,表示“而且”,只有当&&
连接的两条或者多条命令都成立时,返回值才为0。使用test
时,&&
改为-a
。
||
:逻辑或,表示“或者”,||
连接的两条或者多条命令,只要其中一条命令执行成功,返回值就是0,。使用test
时,||
改为-o
。
!
:逻辑非,表示“否”,只有当条件不成立时,命令执行的返回值才会为0。
如:判断当前用户是否是root,如果是输出“user is root”,反之输出“user isn’t root”
$ user=`who am i | awk '{print $1}'`
$ [ $user == "root" ] || echo "user isn't root" && echo "user is root"
user is root
整数运算
Shell变量的数值运算多用于脚本程序的过程控制(如循环次数、使用量比较等)。在 Bash 环境中,只能进行简单的整数运算,不支持小数运算。
Shell 本身支持的两种运算表达式:$(())
和 $[]
常用的运算符:
+:加
-:减
*:乘
/:除
%:求模,取余
如:
$ echo $((1+1))
2
$ echo $[1+1]
2
命令运算
除了 Shell 本身的算数运算表达式,还有几个命令支持复杂的算数运算
命令 | 描述 | 示例 |
---|---|---|
let | 赋值并运算,支持++、– | let VAR=(1+2)*3; echo $VAR x=10 let x++; echo $x 每执行一次let x++,x的值加1 let x–; echo $x 每执行一次let x–,x的值减1 let x+=2 每执行一次x加2 let x-=2 每执行一次x减2 |
expr | 乘法,需要加转义 \ | expr 1 \* 2 运算符两边必须有空格 expr \( 1 + 2 \) \* 2 使用括号要转义 |
bc | 计算器,支持浮点运算(小数点)、平方 | bc 本身就是一个计算器,和windows的cale一样,输入命令,可直接进入解释器进行运行即可 echo “1 + 2” | bc 使用bc计算echo输出的运算 echo “1.2 + 2” | bc echo “10^2” | bc 表示10的2次方 echo ‘scale=2;10/3’ | bc 用scale保留2位小数 |
Shell 不支持浮点数比较,可以借助 bc 来完成需求:
# 符号:< 、>、==、!=
$ echo "1.2 < 2" | bc
1
# 返回1为成立,返回0为不成立
expr
还可以用来计算字符串长度
$ expr length "FeiYi"
5
# 截取字符串
$ expr substr "FeiYi" 1 4
FeiY
# 获取字符在字符串中出现的位置:
$ expr index "FeiYi" Fei
1
$ expr index "FeiYi" i
3
# 获取字符串开始字符出现的长度:
$ expr match "FeiYi" F.*
5
$ expr match "FeiYi" Fei
3