一、判断:if
1、单分支模式
if 条件测试
then
命令序列
fi
if 条件测试 ; then
命令序列
fi
案例:
[root@localhost jiaofan]# cat b.sh
#!/bin/bash
if [ -z $1 ]
then
echo "错误:未输入服务名称"
echo "用法:脚本名 服务器名称"
fi
if systemctl is-active $1 &> /dev/null ; then
echo "$1 已经启动"
else
echo "$1 未启动"
exit 1
fi
if systemctl is-enabled $1 &>/dev/null ; then
echo "$1 是开机自选项"
else
echo "$1 不是开机自选项"
fi
[root@localhost jiaofan]# ./b.sh
错误:未输入服务名称
用法:脚本名 服务器名称
未启动
[root@localhost jiaofan]# ./b.sh sshd
sshd 已经启动
sshd 是开机自选项
[root@localhost jiaofan]# ./b.sh mysql
mysql 未启动
[root@localhost jiaofan]#
2、双分支模式
if 条件测试 ; then
命令序列1
else
命令序列2
fi
案例:一键源码安装nginx软件包
[root@localhost jiaofan]# vi install_nginx.sh
#!/bin/bash
#功能描述:一键源码安装nginx软件包
#定义不同的颜色属性
setcolor_failure="echo -en \\033[91m"
setcolor_success="echo -en \\033[32m"
setcolor_normal="echo -en \\033[0m"
#判断是否以管理员身份执行脚本
if [[ $UID -ne 0 ]];then
$setcolor_failure
echo -n "请以管理员身份运行"
$setcolor_normal
exit
fi
#判断系统中是否存在wget下载工具
#wget使用-c选项可以开启断点续传功能
if rpm --quiet -q wget ; then
wget -c http://nginx.org/download/nginx-1.21.6.tar.gz
else
$setcolor_failure
echo -n "未找到wget,请先下载......"
$setcolor_normal
exit
fi
#如果没有nginx账户,则脚本自动创建该账户
if ! id nginx &> /dev/null ; then
adduser -s /sbin/nologin nginx
fi
#测试是否存在正确的源码包软件
#在源码包编译安装之前,先安装相关的依赖包
if [[ ! -f nginx-1.21.6.tar.gz ]];then
$setcolor_failure
echo -n "未找到nginx源码包,请先下载......"
$setcolor_normal
exit
else
yum -y install gcc pcre-devel zlib-devel openssl-devel
clear
$setcolor_success
echo -n "接下来,需要花费几分钟编译安装nginx"
$setcolor_normal
sleep 6
tar -xf nginx-1.21.6.tar.gz
#编译源码包安装 nginx ,指定账户和组,指定安装路径,开启需要的模块,禁用不需要的模块
cd nginx-1.21.6/
./configure \
--user=nginx \
--group=nginx \
--prefix=/data/server/nginx \
--with-stream \
--with-http_ssl_module \
--with-http_stub_status_module \
--without-http_autoindex_module \
--without-http_ssi_module
make
make install
fi
if [[ -x /data/server/nginx/sbin/nginx ]];then
clear
$setcolor_success
echo -n "一键部署 nginx 已经完成"
$setcolor_normal
fi
3、多分支模式
if 条件测试1 ; then
命令序列1
elif 条件测试2 ; then
命令序列2
elif 条件测试3 ; then
命令序列4
... ...
else
命令序列n
fi
案例:脚本自动生成10以内的随机数,根据用户的输入,判断输出结果
[root@localhost jiaofan]# cat guess_num.sh
#!/bin/bash
#功能描述:脚本自动生成10以内的随机数,根据用户的输入,判断输出结果
clear
num=$[RANDOM%10+1]
read -p "请输入1~10之间的整数:" guess
if [ ${guess} -eq ${num} ] ; then
echo "恭喜,猜对了,就是$num"
elif [ $guess -lt $num ];then
echo "Oops,猜小了。"
else
echo "Oops,猜大了。"
fi
[root@localhost jiaofan]# ./guess_num.sh
请输入1~10之间的整数:8
Oops,猜大了。
[root@localhost jiaofan]#
二、选择:case
结束使用 ;; 还是 ;& 。如果使用 ;; 则代表不在往下进行匹配,;& 代表继续往下进行匹配。
case word in
模式1:)
命令序列1;;
模式2:)
命令序列2;;
... ...
模式*:)
命令序列n;;
esac
case word in
模式1|模式2|模式3:)
命令序列1;;
模式4|模式5|模式6:)
命令序列2;;
... ...
模式*:)
命令序列n;;
esac
[root@localhost jiaofan]# cat echo_menu.sh
#!/bin/bash
#功能描述:定义功能菜单,使用case语句判断用户选择的菜单项,实现对应功能
clear
echo -e "\033[42m---------------------------------\033[0m"
echo -e "\e[2;10H 这里是菜单\t\t"
echo -e "#\e[32m 1.查看网卡信息\e[0m #"
echo -e "#\e[33m 2.查看内存信息\e[0m #"
echo -e "#\e[34m 3.查看磁盘信息\e[0m #"
echo -e "#\e[35m 4.查看CPU信息\e[0m #"
echo -e "#\e[36m 5.查看账户信息\e[0m #"
echo -e "\033[42m---------------------------------\033[0m"
echo
read -p "请输入选项【1-5】:" key
case $key in
1)
ip a ;;
2)
mem_liyonglv=`free -t | awk 'NR == 2 {printf("%.2f% "), $3/$2*100}'`
mem=$(free | grep Mem | tr -s " " | cut -d" " -f7)
echo "本机内存剩余容量为:${mem}K。"
echo "本机内存利用率为:${mem_liyonglv}。"
;;
3)
root_free=$(df | grep /$ | tr -s " " | cut -d" " -f4)
echo "本机根分区剩余容量为:${root_free}K。"
;;
4)
cpu=$(uptime | tr -s " " | cut -d" " -f13)
cpu_liyonglv=$(top -b -n1 | head -5 | grep ^%Cpu | awk '{printf("%.2f%"),100-$8}')
echo "本机 cpu 15min 的平均负载为:$cpu。"
echo "本机 cpu 利用率为:$cpu_liyonglv。"
;;
5)
login_number=$(who | wc -l)
total_number=$(cat /etc/passwd | wc -l)
echo "当前系统账号为$USER"
echo "当前登录系统的账号数为:$login_number"
echo "当前系统中总用户数为:$total_number";;
*)
echo "输入有误,超出1-5的范围";;
esac
[root@localhost jiaofan]# ./echo_menu.sh
---------------------------------
这里是菜单
# 1.查看网卡信息 #
# 2.查看内存信息 #
# 3.查看磁盘信息 #
# 4.查看CPU信息 #
# 5.查看账户信息 #
---------------------------------
请输入选项【1-5】:2
本机内存剩余容量为:283784K。
本机内存利用率为:56.14% 。
[root@localhost jiaofan]#
案例2:不区分y和yes
[root@localhost jiaofan]# sh case-demo3.sh
你确定需要执行该操作吗(y|n)y
注意:你选择的是yes
[root@localhost jiaofan]# sh case-demo3.sh
你确定需要执行该操作吗(y|n)no
你选择的是no
[root@localhost jiaofan]# cat case-demo3.sh
#!/bin/bash
#功能描述:交互脚本,识别用户的输入信息
#可以输入y或yes,不区分大小写
#可以输入n或no,不区分大小写
#使用|分隔多个模式匹配,表示或关系,匹配任意模式即可成功
read -p "你确定需要执行该操作吗(y|n)" key
case $key in
[Yy]|[Yy][Es][Ss])
echo "注意:你选择的是yes";;
[Nn]|[Nn][Oo])
echo "你选择的是no";;
*)
echo "无效的输入";;
esac
[root@localhost jiaofan]#
三、循环:for、while
for name [ in [ word jiaofan ... ] ]
do
命令序列
done
for name #<==默认取值为$@
do
命令序列
done
for (( i=1 ; i<=8 ; i++ ))
do
命令序列
done
while 条件判断
do
命令序列
done
案例一:自动生成数
[root@localhost ~]# cat chess.sh
#!/bin/bash
#功能描述:打印国际象棋棋盘
for i in {1..8}
do
for j in {1..8}
do
sum=$[i+j]
if [[ $[sum%2] -ne 0 ]];then
echo -ne "\e[41m \e[0m"
else
echo -ne "\e[47m \e[0m"
fi
done
echo
done
四、until和select
until 和 while 刚刚相反,until 是满足条件时退出循环。
until 条件判断
do
命令序列
done
select 变量名 in 值列表
do
命令序列
done
案例1:了解until
[root@localhost jiaofan]# ./until.sh
1
2
3
4
5
[root@localhost jiaofan]# cat until.sh
#!/bin/bash
#until 语句仅当条件判断为真时才退出循环
i=1
until [[ $i > 5 ]]
do
echo $i
let i++
done
[root@localhost jiaofan]#
案例2:了解 select
[root@localhost jiaofan]# cat b.sh
#!/bin/bash
select i in {1..4}
do
echo $i
done
[root@localhost jiaofan]# ./b.sh
1) 1
2) 2
3) 3
4) 4
#? 2
2
#? 4
4
#? ^C
[root@localhost jiaofan]#
案例3:了解 select
[root@localhost jiaofan]# cat a.sh
#!/bin/bash
echo "请根据提示选择一个选项"
select item in "CPU" "ip" "mem" "exit"
do
case $item in
"CPU")
uptime;;
"ip")
ip a s;;
"mem")
free;;
"exit")
exit;;
*)
echo error;
esac
done
[root@localhost jiaofan]# ./a.sh
请根据提示选择一个选项
1) CPU
2) ip
3) mem
4) exit
#? 1
16:35:55 up 6:35, 1 user, load average: 0.00, 0.01, 0.05
#? 4
[root@localhost jiaofan]#
五、中断与退出:continue、break 和 exit
命令 | 作用 |
---|---|
continue | 结束单词循环,比如循环10次,但是第三次不用循环,这时就可以用这个跳出第三次循环 |
break | 结束整个循环体 |
exit | 退出程序,不管还有多少没有执行的,反正就是结束了 |
正常情况下:
[root@localhost jiaofan]# ./cbe.sh
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
[root@localhost jiaofan]# cat cbe.sh
#!/bin/bash
#测试continue、break、exit
for i in {1..5}
do
for ((j=0;j<5;j++))
do
echo -n "* "
done
echo
done
案例2:continue测试:当$i=3 && $j=3时,也就是打印第三行第三列时,执行continue,可以看到没有打印33
[root@localhost jiaofan]# ./cbe.sh
10 11 12 13 14
20 21 22 23 24
30 31 32 34
40 41 42 43 44
50 51 52 53 54
[root@localhost jiaofan]# cat cbe.sh
#!/bin/bash
#测试continue、break、exit
for i in {1..5}
do
for ((j=0;j<5;j++))
do
if [[ $i -eq 3 && $j -eq 3 ]] ;then
continue
fi
echo -n "$i$j "
done
echo
done
[root@localhost jiaofan]#
案例3:break:在每一行执行到第三例时遇到break,可以看到直接跳出了循环,但是仍然会执行外循环。break可以跳出自己所在的for循环。
[root@localhost jiaofan]# ./cbe.sh
10 11 12
20 21 22
30 31 32
40 41 42
50 51 52
[root@localhost jiaofan]# cat cbe.sh
#!/bin/bash
#测试continue、break、exit
for i in {1..5}
do
for ((j=0;j<5;j++))
do
if [[ $j -eq 3 ]] ;then
break
fi
echo -n "$i$j "
done
echo
done
[root@localhost jiaofan]#
案例4:exit:遇到exit,直接退出脚本
[root@localhost jiaofan]# ./cbe.sh
10 11 12 [root@localhost jiaofan]# cat cbe.sh
#!/bin/bash
#测试continue、break、exit
for i in {1..5}
do
for ((j=0;j<5;j++))
do
if [[ $j -eq 3 ]] ;then
exit #<==直接退出脚本
fi
echo -n "$i$j "
done
echo
done
[root@localhost jiaofan]#
六、IFS 默认分隔符
在Shell 中使用内部变量IFS (Internal Field Seprator)来决定项目列表或值列表的分隔符,IFS 的默认值为空格、Tab 制表符或换行符。使用 for 循环读取项目列表或值列表时,就会根据IFS 的值判断列表中值的个数,最终决定循环的次数。
特殊的控制字符,可以设置分隔符为特殊控制字符。
控制字符 | 描述 |
---|---|
\a | Bell响铃符 |
\b | Backspace退格符 |
\f | Form Feed 换行符,光标仍旧停留在原来的位置 |
\n | New Line 换行符,且光标移至行首 |
\r | Return 光标移至行首,但不换行 |
\t | Horizontal Tab 水平制表符 |
\v | Vertical Tab 垂直制表符 |
\nnn | 任意八进制字符 |
案例一:输出查看$IFS
[root@localhost ~]# echo $IFS #<==因为IFS的值是空格或Tab制表符,所以无法显示内容,另外IFS的值还是换行符,所以有空行
[root@localhost ~]# printf "%s" $IFS #<==printf 也无内容
[root@localhost ~]# printf "%s" "$IFS" | od -b #<==转换成八进制看看,040是空格键、011是Tab制表符、012是换行符。
0000000 040 011 012
案例二:修改IFS
[root@localhost ~]# OLD_IFS="$IFS" #<==备份原来的,也可以自己设置默认值
[root@localhost ~]# IFS=";" #<==设置分隔符为“;”
[root@localhost ~]# read -p "请输入3个数字:" x y z #<==以空格为分隔符测试
请输入3个数字:a b c
[root@localhost ~]# echo $x
a b c #<==abc三个值都分给你x
[root@localhost ~]# echo $y $z
[root@localhost ~]# read -p "请输入3个数字:" x y z #<==以分号为分隔符测试
请输入3个数字:a;b;c
[root@localhost ~]# echo $x #<==成功
a
[root@localhost ~]# echo $y
b
[root@localhost ~]# echo $z
c
[root@localhost ~]# IFS="$OLD_IFS" #<==恢复之前的值。
案例三:设置IFS为特殊控制字符
错误设置
[root@localhost ~]# IFS="\t" #错误设置,实际这是以字母t为分隔符
[root@localhost ~]# read -p "请输入3个数字:" x y z
请输入3个数字:a b c #<==中间是Tab键进行分隔的
[root@localhost ~]# echo $x #<==测试结果是设置错误
a b c
[root@localhost ~]# echo $y $z
[root@localhost ~]# read -p "请输入3个数字:" x y z #<==测试是不是以t为分隔符
请输入3个数字:atbtc
[root@localhost ~]# echo $x
a
[root@localhost ~]# echo $y
b
[root@localhost ~]# echo $z
c
正确设置:$‘string’ 必须是单引号
[root@localhost ~]# IFS=$"\t" #<==双引号设置出现错误
[root@localhost ~]# read -p "请输入3个数字:" x y z
请输入3个数字:a b c
[root@localhost ~]# echo $x
a b c
[root@localhost ~]# IFS=$'\t' #<==单引号设置成功
[root@localhost ~]# read -p "请输入3个数字:" x y z
请输入3个数字:a b c
[root@localhost ~]# echo $x
a
[root@localhost ~]# echo $y
b
[root@localhost ~]# echo $z
c
[root@localhost ~]# IFS=$' \t\n' #<==恢复默认设置:空格、Tab制表符或换行符。