1.Shell条件测试
1.1.数值比较:
操作符:
- gt:大于
- lt:小于
- eq:等于
- ne:不等于
- ge:大于等于
- le:小于等于
测试语法:
- 方式1:
test 条件表达式
[root@VM-0-17-centos ~]# test 8 -ge 2 // 直接执行该命令是没有返回值的 [root@VM-0-17-centos ~]# [root@VM-0-17-centos ~]# test 8 -ge 0;echo $? 0
- 方式2:
[条件表达式]
(条件表达式和[]之间一定要有空格)[root@VM-0-17-centos ~]# [ 7 -eq 7 ] // 直接执行该命令是没有返回值的 [root@VM-0-17-centos ~]# [ 7 -eq 7 ];echo $? 0
- 方式3:
[[条件表达式]]
(条件表达式和[[]]之间一定要有空格,且两个[]之间不能有空格)[root@VM-0-17-centos ~]# [[ 7 -eq 7 ]];echo $? 0 [root@VM-0-17-centos ~]# [[ 7 -eq 7 ]] // 直接执行该命令是没有返回值的 [root@VM-0-17-centos ~]#
测试脚本:
read -p "输入密码:" ps if [ ${#ps} -lt 7 ] then echo "too short" else echo "too long" fi // 表示if结束
tips:
- 获取变量长度:
[root@VM-0-17-centos ~]# a="psj" [root@VM-0-17-centos ~]# echo ${#a} //一定要加上{} 3
echo $?
表示返回上一条命令的返回值,返回值为0表示上一条命令执行正常
1.2.文件测试:
- 操作符:
-f filename
:当filename
存在时返回真-b pathname
:当pathname
存在且是一个目录时返回真-w pathname
:当pathname
存在且可写时返回真- …
- 测试语法:同数值比较部分中的三种方式
- 测试脚本:
read -p "输入备份目录:" dir if [ -d $dir ] then echo "$dir可以备份" else echo "$dir不可备份" fi
1.3.字符串判断:
- 操作符:
=
:等于,也可以使用==
!=
:不等于,也可以使用!==
- 测试语法:同数值比较部分中的三种方式
- 测试脚本:
read -p "输入字符串:" str if [ $str = "ok" ] then echo "ok!" else echo "not ok!" fi
tips:
- 判断字符长度是否为0:
[root@VM-0-17-centos ~]# a="" [root@VM-0-17-centos ~]# [ -z "$a"];echo $? // 等价于[ ${#a} -eq 0 ];echo $?
1.4.and和or:
操作符:
&&
:逻辑与,可以使用-a
替代
||
:逻辑或,可以使用-o
替代测试语法:同数值比较部分中的三种方式
测试脚本:
read -p "输入密码:" pass # if [ "${#pass}" -gt 1 -a "${#pass}" -lt 5 ] # if [ "${#pass}" -gt 1 && "${#pass}" -lt 5 ] // 报错,如果使用了&&只能使用[[]] if [[ "${#pass}" -gt 1 && "${#pass}" -lt 5 && "$pass" =~ [a-z] ]] then echo "nice" else echo "bad" fi
tips:
- 如果在判断表达式中使用到了特殊字符,只能使用
[[]]
,比如在测试脚本中出现~
(=~
为正则表达式的模糊查询)和$$
,如果使用[]
会报错
2.流程控制
- 单分支:
if [ 表达式 ] then // 执行语句 fi
- 双分支:用户输入用户名,如果该用户名不存在就创建该用户
read -p "输入用户名:" name id $name &> /dev/null // 原本执行id会输出内容,但是&> /dev/null后不会输出内容,但命令是否正确执行可以使用$?显示 if [ $? -ne 0 ] then useradd $name else echo "用户已经存在!" fi
- 多分支:获取当前时间进行判断输出
hour=`date +%H` // 获取当前时间的小时数 if [ $hour -ge 6 -a $hour -le 10 ] then echo "morning" elif [ $hour -ge 11 -a $hour -le 13 ] then echo "noon" elif [ $hour -ge 14 -a $hour -le 18 ] then echo "afternoon" else echo "night" fi
- 嵌套结构:
read -p "输入用户名:" user # 判断用户是否存在 if id $user &> /dev/null // 如果直接在if中使用命令,则不能在两边加上[] then echo "用户已经存在" else echo "准备创建用户" read -p "输入新用户密码:" pass if [ ${#pass} -ge 7 ] then useradd $user echo $pass | passwd --stdin $user else echo "密码不符合要求" fi fi
tips:
- 检测脚本中是否有语法错误:
# 使用参数-n检测语法错误 [root@VM-0-17-centos ~]# bash -n test.sh // 有语法错误会输出信息,没有错误也不会执行脚本 test.sh: line 4: syntax error near unexpected token `then' test.sh: line 4: `then' # 使用参数-vx逐行执行命令,执行成功的命令会出现加号 [root@VM-0-17-centos ~]# bash -vx test.sh read -p "输入用户名:" user + read -p 输入用户名: user 输入用户名:root # 判断用户是否存在 if id $user &> /dev/null then echo "用户已经存在" else echo "准备创建用户" read -p "输入新用户密码:" pass if [ ${#pass} -ge 7 ] then useradd $user echo $pass | passwd --stdin $user else echo "密码不符合要求" fi fi + id root + echo 用户已经存在 用户已经存在
- 判断是不支持浮点值的
- 直接在
if
中使用命令是不能在两边加上[]
3.模式匹配:case
- 简单的模式匹配案例:
read -p "输入删除的用户名:" user read -p "确认删除吗?:" action case $action in Y|y|yes|YES|YeS) userdel -r "$user" echo "$user 已经删除" ;; *) echo “bye” ;; esac
- 简单的JumpServer:
web1=192.168.142.149 web2=192.168.142.150 mysql=192.168.142.151 # 打印菜单 cat <<EOF 1.web1 2.web2 3.mysql EOF read -p "输入数字:" num case $num in 1) ssh psj@web1 ;; 2) ssh psj@web1 ;; 3) ssh psj@web1 ;; *) echo "bye" ;; esac