shell脚本进阶
bash条件判断
条件测试类型
条件测试的表达式
[root@localhost ~]#[ 1 -le 2 ]
[root@localhost ~]#echo $?
0
[root@localhost ~]#
[root@localhost ~]#[[ 1 -le 2 ]]
[root@localhost ~]#echo $?
0
[root@localhost ~]#
[root@localhost ~]#test 1 -le 2
[root@localhost ~]#echo $?
0
[root@localhost ~]#
整数测试
-eq //测试两个整数是否相等
-ne //测试两个整数是否不等
-gt //测试一个数是否大于另一个数
-lt //测试一个数是否小于另一个数
-ge //大于或等于
-le //小于或等于
[root@localhost ~]#[ 1 -eq 1 ]
[root@localhost ~]#echo $?
0
字符测试
== //等值比较,检查==两边的内容是否一致,==两边都要有空格
!= //检查两边内容是否不一致,不一致为真,一致为假
=~ //左侧字符串是否能够被右侧的PATTERN所匹配到。此表达式应用于双中括号[[]]中
-z "string" //测试指定字符串是否为空,空则为真,不空则为假
-n "string" //测试指定字符串是否不空,不空则为真,空则为假
[root@localhost ~]#[ 'hyt' == 'hyo' ]
[root@localhost ~]#echo $?
1
[root@localhost ~]#[ 'hyt' == 'hyt' ]
[root@localhost ~]#echo $?
0
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
read -p '你好,请输入:' num1
if [ -z $num1 ];then
echo '你输入错误:' $num1
else
echo '你输入的是:' $num1
fi
[root@localhost ~]#
[root@localhost ~]#./test.sh
你好,请输入:555
你输入的是: 555
[root@localhost ~]#./test.sh
你好,请输入:
你输入错误:
[root@localhost ~]#
文件测试
[root@localhost ~]#ls
anaconda-ks.cfg haproxy test.sh
[root@localhost ~]#[ -f anaconda-ks.cfg ]
[root@localhost ~]#echo $?
0
[root@localhost ~]#
[root@localhost ~]#[ -d /usr/src/ ]
[root@localhost ~]#echo $?
0
[root@localhost ~]#
[root@localhost ~]#echo 123 > abc
[root@localhost ~]#[ -s abc ]
[root@localhost ~]#echo $?
0
[root@localhost ~]#
//存在性测试:
-e //测试文件是否存在
//存在性及类别测试:
-b //测试文件是否为块设备文件
-c //测试文件是否为字符设备文件
-h //测试文件是否为符号链接文件
-L //测试文件是否为符号链接文件
-p //测试文件是否为命名管道文件
-S //测试文件是否为套接字文件
//文件权限测试:
-r //测试当前用户对指定文件是否有读权限
-w //测试当前用户对指定文件是否有写权限
-x //测试当前用户对指定文件是否有执行权限
//文件特殊权限测试:
-g //测试文件是否有sgid权限
-u //测试文件是否有suid权限
-k //测试文件是否有sticky权限
//文件是否打开测试:
-t fd //fd表示的文件描述符是否已经打开且与某终端相关
//双目测试:
file1 -ef file2 //测试file1与file2是否指向同一个设备上的相同inode,说白点就是两者是不是同一个文件
file1 -nt file2 //测试file1是否比file2新
file1 -ot file2 //测试file1是否比file2旧
//无分类:
-N //测试文件自从上一次被读取之后是否被修改过
-O //测试文件是否存在并且被当前用户拥有
-G //测试文件是否存在并且默认组是否为当前用户组
组合测试条件
[root@localhost ~]#[ 1 -eq 1 -a 2 -le 3 ]
[root@localhost ~]#echo $?
0
[root@localhost ~]#[ 1 -eq 1 -a 2 -gt 3 ]
[root@localhost ~]#echo $?
1
[root@localhost ~]#
[root@localhost ~]#[ 1 -eq 1 -o 2 -gt 3 ]
[root@localhost ~]#echo $?
0
[root@localhost ~]#
[root@localhost ~]#[ ! 1 -gt 1 ]
[root@localhost ~]#echo $?
0
[root@localhost ~]#[ 1 -gt 1 ]
[root@localhost ~]#echo $?
1
[root@localhost ~]#
条件判断和控制结构
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
read -p "请输入你的分数:" score
if [ -z $score ];then
echo "你没有输入分数,请重试"
exit
elif [ $score -gt 100 ];then #可以有多个
echo "你输入的分数有误,请重试"
exit
elif [ $score -ge 90 ];then
echo "优"
elif [ $score -ge 80 ];then
echo "良"
elif [ $score -ge 70 ];then
echo "中"
elif [ $score -ge 60 ];then
echo "及格"
else #只能有一个
echo "不及格"
fi
[root@localhost ~]#./test.sh
请输入你的分数:
你没有输入分数,请重试
[root@localhost ~]#./test.sh
请输入你的分数:101
你输入的分数有误,请重试
[root@localhost ~]#./test.sh
请输入你的分数:90
优
[root@localhost ~]#./test.sh
请输入你的分数:80
良
[root@localhost ~]#./test.sh
请输入你的分数:50
不及格
[root@localhost ~]#
分支选择
case语句设置脚本启动httpd服务,设置开机自启
[root@localhost init.d]# cat httpd #脚本文件要放到/etc/init.d/目录下
#!/bin/bash
# chkconfig: 35 40 60 #第一个数运行级别,第二个数启动顺序,第三给数结束顺序,后二为100
# description: start httpd #描述信息
case $1 in
"start")
/usr/local/httpd/bin/apachectl start
;;
"stop")
/usr/local/httpd/bin/apachectl stop
;;
"restart")
/usr/local/httpd/bin/apachectl stop
/usr/local/httpd/bin/apachectl start
;;
"status")
status=$(ps -ef|grep "httpd"|grep -Ev "grep|$0 status"|wc -l)
if [ $status -gt 0 ];then
echo "httpd is running"
else
echo "httpd is dead"
fi
;;
*)
echo "usage:start|stop|restart|status"
;;
esac
[root@localhost init.d]#
* //任意长度任意字符
? //任意单个字符
[] //指字范围内的任意单个字符
abc|bcd //abc或bcd
循环语句
特点:循环语句需要有一个进入条件和一个退出条件, 在已知循环次数环境中使用for循环
for循环
for 变量 in 列表; do
循环体
//如何生成列表:
{1..100}
seq [起始数] [步进长度] 结束数
#案例,一次一个的取出5个数
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
for a in $( seq 5 );do
echo $a
done
[root@localhost ~]#
for ((expr1;expr2;expr3))
{
循环体
}
for (( expr1 ; expr2 ; expr3 ));do
循环体
done
expr1 //用于指定初始条件,给控制变量一个初始值
expr2 //判定什么时候退出循环
expr3 //修正expr1指定的变量的值
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
for ((i=0;i<=5;i++)){
echo $i
}
[root@localhost ~]#./test.sh
0
1
2
3
4
5
[root@localhost ~]#
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
for ((i=0;i<=5;i++))do
echo $i
done
[root@localhost ~]#./test.sh
0
1
2
3
4
5
[root@localhost ~]#
while循环
while循环适用于循环次数未知的场景,注意要有退出条件。 条件满足时进入循环,条件不满足了退出循环。
while循环正常用法
while 条件; do
statement 循环体
done
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
i=0
flag=true
while $flag;do
echo $i
let i++
if [ $i -gt 10 ];then
flag=false
fi
done
[root@localhost ~]#
while循环特殊用法
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
i=0
while true;do #这里的true可以改为冒号
echo $i
let i++
done
[root@localhost ~]#
while循环特殊用法二:逐行读取某文件,将值存入line变量中
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
i=0
while read line;do
echo welcome my world
echo $line
let i++
done < passwd
echo $i #统计有多少行
[root@localhost ~]#
[root@localhost ~]# ./1.sh
welcome my world
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
welcome my world
systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin
welcome my world
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:nologin
welcome my world
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
welcome my world
unbound:x:997:995:Unbound DNS resolver:/etc/unbound:/sbin/nologin
welcome my world
sssd:x:996:993:User for sssd:/:/sbin/nologin
welcome my world
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
welcome my world
ntp:x:38:38::/etc/ntp:/sbin/nologin
welcome my world
yzw:x:1000:1000::/home/yzw:/bin/bash
welcome my world
yzw1:x:1001:1001::/home/yzw1:/bin/bash
welcome my world
apache:x:995:992::/home/apache:/bin/bash
25
until循环
条件不满足时进入循环,条件满足了退出循环,和while循环相反
[root@localhost ~]# cat 1.sh
#!/bin/bash
i=0
until [ $i -gt 10 ];do
echo $i
let i++
done
[root@localhost ~]#
循环语句特殊情况
break [num]:提前退出循环。当循环语句中出现break时,将提前退出循环,不再执行循环后面的语句
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
for i in $( seq 10 );do
for q in $( seq 10 );do
if [ $q -gt 5 ];then
break 2
fi
echo $q
done
echo $i
done
[root@localhost ~]#./test.sh
1
2
3
4
5
[root@localhost ~]#
continue [num]:提前结束本轮循环而进入下一轮循环。当循环语句执行到continue时,continue后面的语句将不再执行,提前进入下一轮循环
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
for i in $( seq 10 );do
if [ $i -eq 5 ];then
continue
fi
echo $i
done
[root@localhost ~]#./test.sh
1
2
3
4
6
7
8
9
10
[root@localhost ~]#
定义脚本退出状态码
exit # //此处的#号是一个数字,其范围可以是0-255
#如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码
#注意:脚本中一旦遇到exit命令,脚本会立即终止
[tom@localhost tmp]$ cat 1.sh
#!/bin/bash
if [ $UID -ne 0 ];then
exit 120
fi
[tom@locatlhost tmp]$
[tom@locatlhost tmp]$ ./1.sh
[tom@locatlhost tmp]$ echo $?
120
99乘法表
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
for a in $(seq 9 );do
for b in $(seq $a);do
echo -ne $b"x"$a"="$(( $a*$b ))"\t"
done
echo
done
[root@localhost ~]#./test.sh
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
1x4=4 2x4=8 3x4=12 4x4=16
1x5=5 2x5=10 3x5=15 4x5=20 5x5=25
1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
[root@localhost ~]#