条件判断:
test/[]:
test和[]用来进行条件测试,如果条件成立表示为真,返回0;如果条件不成立表示为假,返回1。
[root@localhost ~]# num=2
[root@localhost ~]# test $num -gt 1 #测试变量num是否大于1。
[root@localhost ~]# echo $?
0
[root@localhost ~]# test $num -gt 2 #测试变量num是否大于2。
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ $num -eq 2 ] #测试变量num是否等于2。
[root@localhost ~]# echo $?
0
test选项:
- -b<文件>:如果文件为一个块特殊文件,则为真。
- -c<文件>:如果文件为一个字符特殊文件,则为真。
- -d<文件>:如果文件为一个目录,则为真。
- -e<文件>:如果文件存在,则为真。
- -f<文件>:如果文件为一个普通文件,则为真。
- -g<文件>:如果设置了文件的SGID位,则为真。
- -G<文件>:如果文件存在且归该组所有,则为真。
- -k<文件>:如果设置了文件的粘着位,则为真。
- -O<文件>:如果文件存在并且归该用户所有,则为真。
- -p<文件>:如果文件为一个命名管道,则为真。
- -r<文件>:如果文件可读,则为真。
- -s<文件>:如果文件的长度不为零,则为真。
- -S<文件>:如果文件为一个套接字特殊文件,则为真。
- -u<文件>:如果设置了文件的SUID位,则为真。
- -w<文件>:如果文件可写,则为真。
- -x<文件>:如果文件可执行,则为真。
判断表达式:
if test #表达式为真。
if test ! #表达式为假。
test 表达式1 –a 表达式2 #两个表达式都为真。
test 表达式1 –o 表达式2 #两个表达式有一个为真。
test 表达式1 ! 表达式2 #条件求反。
判断字符串:
test –n 字符串 #字符串的长度非零。
test –z 字符串 #字符串的长度是否为零。
test 字符串1=字符串2 #字符串是否相等,若相等返回true。
test 字符串1!=字符串2 #字符串是否不等,若不等反悔false。
判断整数:
test 整数1 -eq 整数2 #整数相等。
test 整数1 -ge 整数2 #整数1大于等于整数2。
test 整数1 -gt 整数2 #整数1大于整数2。
test 整数1 -le 整数2 #整数1小于等于整数2。
test 整数1 -lt 整数2 #整数1小于整数2。
test 整数1 -ne 整数2 #整数1不等于整数2。
判断文件:
test File1 –ef File2 两个文件是否为同一个文件,可用于硬连接。主要判断两个文件是否指向同一个inode。
test File1 –nt File2 判断文件1是否比文件2新。
test File1 –ot File2 判断文件1比是否文件2旧。
test –b file #文件是否块设备文件。
test –c File #文件并且是字符设备文件。
test –d File #文件并且是目录。
test –e File #文件是否存在 (常用)。
test –f File #文件是否为正规文件 (常用)。
test –g File #文件是否是设置了组id。
test –G File #文件属于的有效组ID。
test –h File #文件是否是一个符号链接(同-L)。
test –k File #文件是否设置了Sticky bit位。
test –b File #文件存在并且是块设备文件。
test –L File #文件是否是一个符号链接(同-h)。
test –o File #文件的属于有效用户ID。
test –p File #文件是一个命名管道。
test –r File #文件是否可读。
test –s File #文件是否是非空白文件。
test –t FD #文件描述符是在一个终端打开的。
test –u File #文件存在并且设置了它的set-user-id位。
test –w File #文件是否存在并可写。
test –x File #文件属否存在并可执行。
条件分支:
if:
和C语言类似,在Shell中用if,then,elif,else,fi这几条命令实现分支控制。这种流程控制语句本质上也是由若干条Shell命令组成的。
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
其实是三条命令:
第一条:if[ -f ~/.bashrc ] #判断home目录的.bashrc是普通文件的话返回真。
第二条:then . ~/.bashrc #让home目录下的.bashrc里的设置生效。
第三条:fi #表示结束if语句。
和[]一样,if命令的参数组成一条子命令,如果该子命令的Exit Status为0表示真,则执行then后面的子命令,如果Exit Status非0表示假,则执行elif,else或者后面的子命令。
else:
[root@localhost shell]# vim test.sh
#!/bin/sh
if [ -f /bin/bash ] #判断/bin/bash是否是普通文件
then
echo "/bin/bash is a file" #如果返回真输出"/bin/bash is a file"
else
echo "/bin/bash is not a file" #如果返回假输出"/bin/bash is not a file"
fi
if :; then echo "always true"; fi #":"是一个特殊的命令,这个命令不需要做任何事,但是执行结构总是为真。
[root@localhost shell]# ./test.sh
/bin/bash is a file
always true #由于":"的执行结构总是真,所以执行了then来输出"always true"。
elif:
[root@localhost shell]# vim test.sh
#!/bin/sh
echo "is it morning? Please anser yes or on"
read YES_OR_NO #read命令的作用是等待用户输入一行字符串,将该字符串存到YES_OR_NO中。
if [ "$YES_OR_NO" = "yes" ]; then #判断用户的输入,如果$YES_OR_NO为yes,则输出 "Good morning!"。
echo "Good morning!"
elif [ "$YES_OR_NO" = "no" ]; then #判断用户的输入,如果$YES_OR_NO为no,则输出 "Good afternoon!"。
echo "Good afternoon!"
else #如果用户输入的既不是yes也不是no,则输出"Sorry,$YES_OR_NO not recognized.Enter yes or no."。
echo "Sorry,$YES_OR_NO not recognized.Enter yes or no."
exit 1
fi
[root@localhost shell]# ./test.sh
is it morning? Please anser yes or on
no
Good afternoon!
[root@localhost shell]# ./test.sh
is it morning? Please anser yes or on
yes
Good morning!
[root@localhost shell]# ./test.sh
is it morning? Please anser yes or on
saasd
Sorry,saasd not recognized.Enter yes or no.
&&和||:
Shell提供了&&和||语法,和C语言类似具有Short-circuit(短路原则)特性。
- &&相当于“if…then…”。
- ||相对于“if not…then…”。
#ping百度,成功返回yes,失败返回no。
[root@localhost shell]# ping www.baidu.com && echo yes || echo no
PING www.a.shifen.com (61.135.169.125) 56(84) bytes of data.
64 bytes from 61.135.169.125 (61.135.169.125): icmp_seq=1 ttl=56 time=793 ms
^C
--- www.a.shifen.com ping statistics ---
2 packets transmitted, 1 received, 50% packet loss, time 1450ms
rtt min/avg/max/mdev = 793.257/793.257/793.257/0.000 ms
yes
[root@localhostn shell]# ping www.asdasdasda.com && echo yes || echo no
PING HDRedirect-LB5-1afb6e2973825a56.elb.us-east-1.amazonaws.com (23.20.239.12) 56(84) bytes of data.
^C
--- HDRedirect-LB5-1afb6e2973825a56.elb.us-east-1.amazonaws.com ping statistics ---
18 packets transmitted, 0 received, 100% packet loss, time 17002ms
no
case/esac:
case命令可类比C语言的switch/case语句,esac表示擦色语句块的结束。
C语言的case只能匹配整数或字符型常量表达式,而Shell脚本的case可以匹配字符串和Wildcard,每个匹配分支可以有若干条命令,末尾必须以;;结束,执行时找到第一个匹配的分支并执行相应的命令,然后直接跳到esac之后,不需要像C语言一样用break跳出。
[root@localhost shell]# vim test.sh
#!/bin/sh
echo "is it morning? Please anser yes or on"
read YES_OR_NO
case "$YES_OR_NO" in
yes|y|Yes|YES|yEs|yeS|Y)
echo "Good morning!";;
n|N|No|nO|no|NO)
echo "Good afternoon!";;
*)
echo "Sorry,$YES_OR_NO not recognized.Enter yes or no."
exit 1;;
esac
[root@localhost shell]# ./test.sh
is it morning? Please anser yes or on
no
Good afternoon!
[root@localhost shell]# ./test.sh
is it morning? Please anser yes or on
y
Good morning!
[root@localhost shell]# ./test.sh
is it morning? Please anser yes or on
Yes
Good morning!
[root@localhost shell]# ./test.sh
is it morning? Please anser yes or on
SADASD
Sorry,SADASD not recognized.Enter yes or no.