目录
- 1.if 判断
- 1.if-then
- 2.if-then-else
- 3.elif
- 4.case
- 5.实际上手
- 2.条件测试
- 0.事前说明
- 1.test 命令
- 2.[]
- 3.双括号
- 1.(())
- 2.[[]]
- 4.实际上手
- 3.循环
- 1.for
- 2.while
- 3.until命令
- 4.控制循环
- 1.break
- 2.continue
- 5.处理循环的输出
1.if 判断
1.if-then
- 语法:
if command then command fi
- bash的
if
语句和其他编程语言不一样,bash的if
语句会直接运⾏if
后⾯的命令- 如果该命令执⾏正确(状态码为0),处于then的命令就会被执⾏
- 否则就不会执行,或者执行其他逻辑的语句,最后到
fi
结束逻辑控制
2.if-then-else
- 语法:
if command then command else command fi
3.elif
- 语法
if command
then
command
elif command
then
command
fi
4.case
- 可以代替多
if-else
分支case "变量" in 值1) 命令 ;; 值2) 命令2 ;; *) 命令
5.实际上手
- 内存监控
#!/bin/bash FreeMem=`free -m | awk 'NR==2 {print $NF}'` CHARS="Current memory is $FreeMem" if [ "$FreeMem" -lt 16000 ] then echo $CHARS echo "内存不足,抓紧维护服务器!" fi
- 读取比较大小
- 单分支版本
#!/bin/bash a=$1 b=$2 if [ $a -lt $b ] then echo "Yes, $a less than $b" exit 0 fi if [ $a -eq $b ] then echo "Yes, $a equal $b" exit 0 fi if [ $a -gt $b ] then echo "Yes, $a greater than $b" exit 0 fi
- 多分支版本
#!/bin/bash a=$1 b=$2 if [ $a -lt $b ] then echo "Yes, $a less than $b" exit 0 elif [ $a -eq $b ] then echo "Yes, $a equal $b" exit 0 else [ $a -gt $b ] echo "Yes, $a greater than $b" exit 0 fi
- 单分支版本
- MySQL监控脚本
#!/bin/bash if [ `netstat -tunlp | grep mysql | wc -l` -ge "1" ] then echo "MySQL is running" else echo "MySQL is stopped" # systemctl start mysql.service fi
- Rsync启动脚本
#!/bin/bash if [ "$#" -ne 1 ] then echo "Usage: $0 {start|stop|restart}" exit 1 fi if [ "$1" = "start" ] then /usr/bin/rsync --daemon sleep 2 if [ `netstat -tunlp | grep rsync | wc -l` -ge 1 ] then echo "Rsync is started" exit 0 fi elif [ "$1" = "stop" ] then killall rsync &>/dev/null sleep 2 if [ `netstat -tunlp | grep rsync | wc -l` -eq 0 ] then echo "Rsync is stopped" exit 0 fi elif [ "$1" = "restart" ] then kill rsync sleep 1 killpro=`netstat -tunlp | grep rsync | wc -l` /usr/bin/rsync --daemon sleep 1 startpro=`netstat -tunlp | grep rsync | wc -l` if [ "$killpro" -eq 0 -a "$startpro" -ge 1 ] then echo "Rsync is restarted" exit 0 fi else echo "Usage: $0 {start|stop|restart}" exit 1 fi
2.条件测试
0.事前说明
-
条件测试常用的语法
-
常用字符串测试操作符
-
数值比较
-
逻辑操作符
-
各命令对照表
1.test 命令
test
命令最短的定义可能是评估⼀个表达式- 如果条件为真,则返回⼀个0值
- 如果表达式不为真,则返回⼀个⼤于0的值—,也可以将其称为假值
- 检查最后所执⾏命令的状态的最简便⽅法是使⽤
$?
值
- 参数:
-
关于某个文件名的类型侦测(存在与否),如:
test -e filename
参数 意义 -e
该 文件名 是否存在 -f
该 文件名 是否为文件( file
)-d
该 文件名 是否为目录( directory
)-b
该 文件名 是否为 block device
装置-c
该 文件名 是否为一个 character device
装置-S
该 文件名 是否为一个 Socket
文件-p
该 文件名 是否为一个FIFO(pile)文件 -L
该 文件名 是否为一个连接档 -
关于文件的权限侦测,如:
test -r filename
参数 意义 -r
该 文件名 是否具有可读的属性 -w
该 文件名 是否具有可写的属性 -x
该 文件名 是否具有可执行的属性 -u
该 文件名 是否具有SUID的属性 -g
该 文件名 是否具有SGID的属性 -k
该 文件名 是否具有Sticky bit的属性 -s
该 文件名 是否为非空白文件 -
关于两个文件之间的比较,如:
test file1 -nt file2
参数 意义 -nt
(newer than),判断 file1
是否比file2
新-ot
(older than),判断 file1
是否比file2
旧-ef
判断 file1
与file2
是否为同⼀⽂件,可⽤在硬链接的判定上
主要意义在判定,两个⽂件是否均指向同⼀个inode
-
关于两个整数之间的判定,如:
test num1 -eq num2
参数 意义 -eq
两数相等 -ne
两数不相等 -gt
num1
大于num2
-lt
num1
小于num2
-ge
num1
大于等于num2
-le
num1
小于等于num2
-
判定字符串的数据
参数 意义 -z
为空串,则返回 true
-n
不为空串,则为 true
=
str1 == str2
,则返回true
!=
str1 != str2
,则返回true
-
多重条件判断,如:
test -r filename -a -x filename
参数 意义 -a
(and)两状况同时成立 -o
(or)两状况任何一个成立 !
逻辑取反
-
2.[]
- 脚本中经常进行条件测试,用的最多的,就是中括号
[]
test
和[]
的作用是一样的- 基本要素:
[]
两个符号,左右都要有空格分隔- 内部操作符与操作变量之间要有空格,如:
[ "a" = "b" ]
- 字符串比较中,
> <
需要写成\> /<
进行转义 []
中字符串或者${}
变量尽量使用""
双引号括住,避免值未定义引用[ -n "$filename" ]
[]
中可以使用-a -o
进行逻辑运算,不支持&& ||
[]
是bash内置命令
3.双括号
1.(())
- bash支持双小括号,写入高级数学表达式
2.[[]]
- 双中括号提供了针对字符串的⾼级特性,模式匹配,正则表达式的匹配
- 基本要素
[[]]
两个符号,左右都要有空格分隔- 内部操作符与操作变量之间要有空格,如:
[[ "a" = "b" ]]
- 字符串比较中,可以直接使用
> <
,无需转义 [[]]
中字符串或者${}
变量尽量使用""
双引号括住- 如未使用
""
双引号括住的话,会进行模式和元字符匹配
- 如未使用
[[]]
内部可以使用&& ||
进行逻辑运算[[]]
是bash的keyword[[]]
其他用法都和[]
一样
4.实际上手
- 测试逻辑判断
#!/bin/bash read -p "Pls input a char:> " var1 [ "${var1}" -eq 1 ] && { echo ${var1} exit 0 } [ "$var1" -eq 2 ] && { echo $var1 exit 0 } [ "$var1" -ne "1" -a "$var1" -ne "2" ] && { echo "Script Error" exit 1 }
- 模拟安装脚本
#!/bin/bash path=/scripts [ ! -d "$path" ] && mkdir -p scripts cat << END 1.[install lamp] 2.[install inmp] 3.[exit] END read -p "Pls input your choice:> " num # 判断输入是否合法 [[ ! $num =~ [1-3] ]] && { echo "The num you input must be in {1|2|3}" echo "Input Error" exit 1 } [ $num -eq 1 ] && { echo "start installing lamp...waiting..." sleep 2 # 如果该脚本没权限 [ ! -x "$path/lamp.sh" ] || { echo "The file does not exit or can't be exec" exit 2 } # 安装脚本 source ${path}/lamp.sh exit $? } [ $num -eq 2 ] && { echo "start installing lnmp...waiting..." sleep 2 [ ! -x "$path/lnmp.sh" ] || { echo "The file does not exit or can't be exec" exit 3 } source ${path}/lnmp.sh exit $? } [ $num -eq 3 ] && { echo "Bye~" exit 4 }
3.循环
1.for
- 语法:
for var in list do commands done
- 支持C语言风格
for (( i=1;i<=10;i++ )) do echo "The next number is $i" done
2.while
-
语法:此处的
test command
和if-else
语句格式一样,可以使用任何的bash命令- 注意:
while
的test command
的退出状态码,必须随着循环⾥的命令改变,否则状态码如果不变化,循环会不停⽌的继续下去while test command do commands done
- 注意:
-
while
命令可以写入多个测试命令- 只有最后一个测试命令的退出状态码会被决定是否退出循环
- 注意换行,多个测试命令要单独的出现在每一行
var1=10 while echo $var1 [ $var1 -ge 0 ] do echo "This is inside the loop" var1=$[ $var1 -1 ] done
3.until命令
until
和while
是相反的语意,until
命令要求你指定⼀个返回⾮零退出码的测试命令- 只有退出状态码不是0,bash才会执⾏循环的命令
- 语法:
until test commands do other commands done
until
也⽀持多个测试命令,只有最后⼀个决定bash是否执⾏其他命令until echo $var1 [ $var1 -eq 0 ] do echo "Inside the loop:$var1" var1=$[ $var1 - 25 ] done
4.控制循环
1.break
- 作用:强制退出任意类型的循环
- 跳出多个循环时,
break
会自动终止所在的最内存循环
- 跳出多个循环时,
- 终止外层循环:
n
表示跳出的循环层级,默认是1,下一层就是2break n
2.continue
- 作用:跳过某次循环,直接去本次循环的判断部分
5.处理循环的输出
- 在shell脚本⾥,循环输出后的结果,可以进⾏输出重定向
for (( a = 1;a<10;a++ )) do echo "The number is $a" done > test.txt echo "Finished"