在编写shell脚本时,经常遇到的问题就是判断字符串是否相等、文件状态检测、数字测试等,shell脚本中的条件测试语法可以判断表达式是否成立,若条件成立则返回数字0,否则便返回其他随机数值。
test命令:用于测试字符串 、文件状态、数字。
test命令格式:
- test condition
- [ condition ] (使用方括号时注意条件两边加上空格)
条件测试语句可以分为4种:
- 文件测试语句
- 逻辑测试语句
- 数字测试语句
- 字符串测试语句
文件测试
按文件类型:
运算符 | 作用 |
-e | 测试文件是否存在 |
-s | 测试文件是否为非空 |
-b | 测试文件是否为块设备文件 |
-c | 测试文件是否为字符设备文件 |
-d | 测试文件是否为目录类型 |
-f | 测试是否为一般文件 |
-L | 测试是否为软链接文件 |
-S | 测试是否为套接字文件 |
-p | 测试是否为管道文件 |
按文件权限:
-r | 测试当前用户是否有权限读取 |
-w | 测试当前用户是否有权限写入 |
-x | 测试当前用户是否有权限执行 |
两个文件之间比较:
文件1 -nt 文件2 | 文件1的修改时间是否比文件2新 |
文件1 -ot 文件2 | 文件1的修改时间是否比文件2旧 |
文件1 -ef 文件2 | 两个文件的inode节点号是否语言用于判断是否是硬链接 |
文件测试示例
#!/bin/bash
echo "input filename"
read filename
test -e $filename
echo "exist? $?"
#测试文件是否存在
# $? 上一次命令的结果 成功0失败非0
[ -s $filename ]
echo "empty? $?"
#测试文件是否为非空 0代表非空
test -r $filename
echo "can read? $?"
#测试文件是否有读权限
[ -w $filename ]
echo "can write? $?"
#测试文件是否有写权限
运行结果如下 0代表成功
字符串测试语句
表达式 | 功能 |
s1=s2 | 测试两个字符串的内容是否相等 |
s1!=s2 | 测试两个字符串的内容是否有差异 |
-z s1 | 测试s1字符串的长度是否为0 |
-n s1 | 测试s2字符串的长度是否不为0 |
字符串测试示例
#! /bin/bash
test "hello" = "hello"
echo "equal? $?"
test "hello" = "habit"
echo "equal? $?"
test "hello" != "hello"
echo "unequal? $?"
test "hello"!="habit"
echo "unequal? $?"
test -z "hello"
echo "size is zero? $?"
test -n "hello"
echo "size than zero? $?"
结果如下:
数字测试语句
仅对数字的操作,不能和其他内容一起
运算符 | 作用 |
-eq | 是否等于 |
-ne | 是否不等于 |
-gt | 是否大于 |
-lt | 是否小于 |
-le | 是否等于或者小于 |
-ge | 是否大于或者等于 |
示例
#!/bin/bash
echo "please input two numbers "
read num1 num2
[ $num1 -eq $num2 ]
echo "equal? $?"
[ $num1 -ne $num2 ]
echo "not euqal? $?"
[ $num1 -gt $num2 ]
echo "more than? $?"
[ $num1 -ge $num2 ]
echo "than or equal? $?"
[ $num1 -lt $num2 ]
echo "less than ? $?"
[ $num1 -ge $num2 ]
echo "than or equal? $?"
运行结果:
逻辑测试语句
在shell中逻辑与的运算符为 &&,它表示当前面的命令执行成功后才会执行它后面的命令。
逻辑或的运算符为 || ,它表示当前面的命令执行失败后才会执行它后面的命令。
逻辑语句非为 !,它表示把条件测试中的判断结果取反值。
多重条件判定
逻辑测试示例
#! /bin/bash
num=100
#判断0<=num<=200
[ $num -ge 0 ] && [ $num -le 200 ]
echo "$?"
#判断num<=0 或者 num>=200
test $num -le 0 || test $num -ge 200
echo "$?"
#判断文件是否不是普通文件
file="demo4.sh"
test ! -f $file
echo "$?"
#判断文件是否存在并且是否是目录文件
[ -e $file ] && [ -d $file ]
echo "$?"
运行结果 :
控制语句
if控制语句
格式一: if[ 条件1 ]
then 执行第一段程序
else
执行第二段程序
fi
格式二:if [ 条件1 ]
then 执行第一段程序
elif [ 条件2 ]
then 执行第二段程序
else
执行第三段程序
fi
if语句示例:
#!/bin/bash
read num
if [ $num -gt 50 ]
#如果num的值 大于 50
then
echo "num>50"
elif [ $num -lt 50 ]
then
echo "num<50"
else
echo "num=50"
fi
# if 和 elif 后都要跟then else则不用 fi结束
echo "*********************"
#循环嵌套
if [ $num -gt 50 ]
then
echo "num>50"
else
if [ $num -gt 30 ];then
#如果大于30且小于50时
echo "30<num<50"
elif [ $num -lt 30 ]&&[ $num -gt 0 ]
#如果大于0且小于30
then
echo "0<num<30<50"
else
echo " num<0"
fi
fi
运行结果:
case控制语句
case $变量名 in
"第一个变量内容")
程序段一
; ;
"第二个变量内容")
程序段二
; ;
*)
其他程序段
exit 1
esac
单一匹配case:
#! /bin/bash
echo "this script will print your choice"
case "$1" in
"one")
echo "your choice is one"
;;
"two")
echo "your choice is two"
;;
"three")
echo "your chioce is three"
;;
*)
echo " please try again"
exit 1
;;
esac
echo "hello"
#当其他条件触发exit1时会直接退出
#正常情况时打印输出 其他情况不打印
注意exit1会直接退出
当多种情况时:
*是一个通配符,可以匹配任意字符并且任意长度
#!/bin/bash
echo "please input your choice"
read choice
case "$choice" in
Y | Yes | YES | y | yes)
#多种情况同时一种输出
echo "accept"
;;
N* | n* )
#通配符表示匹配N 和 n开头的任意大小
echo "not accept"
;;
*)
exit 1
esac
结果如下:
for控制语句
格式一: for( (初始值;限制值;执行步阶) ) 这里是分号;和c语言类似
do
程序段
done
初始值:变量在循环中的起始值
限制值:当变量处于限制范围内就继续进行循环
执行步阶:每次循环的变化量
declare是bash的一个内建命令,可以用来声明shell变量、设置变量的属性·。declare也可写作 typeset 。
declare -i s 表示强制把s变量当做int型变量运算
格式一的for控制语句示例:
#!/bin/bash
declare -i sum
#声明sum是一个整数变量 只能保存整数
for (( i=0; i<=10; i++ ))
do
sum=i+sum
#循环11次算出0到11的累加和
done
echo "result is $sum"
格式二: for var in con1 con2 con3 ...
do
程序段
done
第一次循环时,$var的内容为con1
第二次循环时,$var的内容为con2
第三次循环时,$var的内容为con3
格式二的for控制语句示例: 加上if测试条件
#!/bin/bash
#注意 for循环后的变量不用加$
for i in 1 2 3 4 5
do
if [ $i -eq 1 ]
#如果i的值为1时输出 找到1
then
echo "find $i"
elif [ $i -eq 3 ]
#如果i的值为3时输出 找到3
then
echo "find $i"
else
echo "$i"
fi
done
结果如下: 当i为1和3时触发条件
把ls 查看到的文件名当成for的变量循环测试 其文件类型 使用mkfifo命令可以创建一个有名管道
#!/bin/bash
for name in `ls`
do
if [ -f $name ];then
echo "$name is file"
elif [ -d $name ];then
echo "$name is dir"
else
echo "$name is ohers"
fi
done
结果如下:
while控制语句
格式: while [ condition ]
do
程序段
done
当condition成立时进入while循环,不成立时退出循环
while控制语句+if控制语句:
#! /bin/bash
declare -i i=0
declare -i s
#声明了两个整型变量
#这里默认初始化值为0
while [ "$i" != "101" ]
do
s+=i
i=i+1
#从0到100的累加和
if [ $i -eq 50 ];then
echo "i'm coming 50"
#当i到达50时打印 其他情况不打印
else
k=10
#这里好像不能空实现会报错 所以执行一条定义
fi
done
echo "count is $s"
结果如下: 也可以使用关键字continue跳出当前循环
until控制语句
格式: until [ condition ]
do
程序段
done
这种方式与while恰恰相反,当条件不成立时继续循环 直到条件成立退出循环
until控制语句+if控制语句:
#! /bin/bash
declare -i i
declare -i s
#当i等于101不成立时一直循环到成立退出
until [ "$i" = "101" ]
do
#0到100的累加和
s+=i;
i=i+1;
#如果i的值到了50打印
if [ $i -eq 50 ];then
echo "i'm coming 50"
else
#这里没有语句会报错
continue
#可使用continue跳出当前循环 和c语言一样
fi
done
echo "result: $s"
结果:
控制语句关键字
break命令允许直接跳出循环,continue则是跳出当前循环继续下一次循环 这里和c语言一样
shell函数
有些脚本代码可重用,shell允许将一组命令集或者语句形成一个可控制块,称为shell函数,可以减少大量重复的脚本代码编写时间。
格式一:
函数名(){
命令 ...
}
格式二:
function 函数名(){
命令 ...
}
注意点:所有函数在使用前必须先定义,必须放在脚本开始部分,直到shell解释器首次发现才可以使用。脚本程序是从上往下执行的。
调用函数的格式为:
函数名 param1 param2 ...
使用参数同在一般脚本中使用特殊变量 $1 $2 $3 ..$9 一样
#! /bin/bash
myprint()
{
echo "hello world"
echo "welcome"
}
#函数定义在脚本开始时
myprint
#函数调用
for (( i=0;i<=4;i++ ))
do
myprint
done
#for循环执行四次 函数
执行结果 : 总共输出5轮
shell函数需传参不能在()里面直接定义 ,而是使用$1 $2 ...等外部传入的值
expr命令可以计算两个数的和
shell传参示例:
#! /bin/bash
myadd()
{
a=$1
b=$2
sum=`expr $a + $b`
#expr命令是两个相加
echo "$a + $b = $sum"
}
myadd 100 200
# 100赋值给$1 200赋值给$2
num1=10 num2=20
myadd $num1 $num2
#这里要使用$传整数值 不然会被认为字符串
结果:
函数返回值
函数可以使用return提前结束并带回返回值
return 从函数中返回,用最后状态命令决定返回值
return 0 无错误返回
return 1 有错误返回
示例:
#! /bin/bash
myadd()
{
a=$1
b=$2
sum=`expr $1 + $2 `
return $sum
}
myadd 10 10
echo "$?"
myadd 100 200
echo "$?"
#小于255的函数返回值可以使用$?返回 超出会出错
echo "sum=$sum"
#在shell除了()里面定义的变量,只要不做任何修饰
#都可以认为是全局变量 可以在任意地方调用
结果:
44是因为使用$?并且值超出了255就会出错
计划任务服务程序:
把周期性、规律性的任务交给系统自动完成,使用at命令部署计划。
计划任务分为一次性计划任务和长期性计划任务,例如:
- 一次性计划任务:今晚10点00分开启网站服务
- 长期性计划任务:每次晚上10点00分开启网站服务
先安装at命令:
设置一次性计划任务时间
at 时间
结束输入设置
按下CTRL + d
查看已经设置但是没有执行的一次性计划任务
at -l
删除尚未开始的计划任务 atrm+job号
atrm job
周期性计划任务
编辑命令
crontab -e
查看命令
crontab -l
删除计划命令
crontab -r
-----------END