随堂练习 shell脚本(四)
流程控制
条件选择
条件判断
单分支条件
选择执行 if 语句
格式
if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
单分支
if 判断条件;then
条件为真的分支代码
fi
双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
多分支
if 判断条件1; then
条件1为真的分支代码
elif 判断条件2; then
条件2为真的分支代码
elif 判断条件3; then
条件3为真的分支代码
...
else
以上条件都为假的分支代码
fi
说明:
多个条件时,逐个条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
if 语句可嵌套
范例
#根据命令的退出状态来执行命令
if ping -c1 -W2 station1 &> /dev/null ; then
echo 'station1 is UP'
elif grep -q 'station1' ~/maintenance.txt; then
echo 'station1 is undergoing maintenance'
else
echo 'station1 is unexpectedly DOWN!'
exit 1
fi
范例:身体质量指数 (BMI)
[root@centos8 ~]# cat if_bmi.sh
#!/bin/bash
read -p "请输入身高(m为单位):" HIGH
if [[ ! "$HIGH" =~ ^[0-2](\.[0-9]{,2})?$ ]]; then
echo "输入错误的身高"
exit 1
fi
read -p "请输入体重(kg为单位):" WEIGHT
if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]]; then echo "输入错误的体重"; exit 1
fi
BMI=`echo $WEIGHT/$HIGH^2|bc`
if [ $BMI -le 18 ]; then
echo "太瘦了,多吃点"
elif [ $BMI -lt 24 ]; then
echo "身材很棒"
else
echo "太胖了,注意节食,加强运动"
fi
条件判断 case 语句
格式
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
case支持glob风格的通配符:
* 任意长度任意字符
? 任意单个字符
[] 指定范围内的任意单个字符
| 或者,如: a|b
范例
[root@centos8 scripts]# cat case_yesorno.sh
#!/bin/bash
read -p "Do you agree(yes/no)?" INPUT
INPUT=`echo $INPUT | tr 'A-Z' 'a-z'`
case $INPUT in
y|yes)
echo "You input is YES"
;;
n|no)
echo "You input is NO"
;;
*)
echo "Input false,please input yes or no !"
esac
[root@centos8 scripts]# cat case_yesorno2.sh
#!/bin/bash
read -p "Do you agree(yes/no)?" INPUT
case $INPUT in
[yY]|[Yy][Ee][Ss])
echo "You input is YES"
;;
[Nn]|[Nn][Oo])
echo "You input is NO"
;;
*)
echo "Input false,please input yes or no !"
esac
范例:运维菜单实现版本2
[root@centos8 scripts]# cat work_menu.sh
#!/bin/bash
echo -en "\E[$[RANDOM%7+31];1m"
cat <<EOF
请选择:
1)备份数据库
2)清理日志
3)软件升级
4)软件回滚
5)删库跑路
EOF
echo -en "\E[0m"
read -p "请输入上面数字1-5:" MENU
case $MENU in
1)
./backup.sh
;;
2)
echo "清理日志"
;;
3)
echo "软件升级"
;;
4)
echo "软件回滚"
;;
5)
echo "删库跑路"
;;
*)
echo "INPUT FALSE !"
esac
练习
1、编写脚本 createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之。并设置初始密码为123456,显示添加的用户的id号等信息,在此新用户第一次登时,会提示用户立即改密码,如果没有参数,就提示:请输入用户名
2、编写脚本 yesorno.sh,提示用户输入yes或no,并判断用户输入的是yes还是no,或是其它信息
3、编写脚本 filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)
4、编写脚本 checkint.sh,判断用户输入的参数是否为正整数
5、编写脚本 reset.sh,实现系统安装后的初始化环境,包括:1、别名 2、环境变量,如PS1等 3、安装常用软件包,如:tree 5、实现固定的IP的设置,6、vim的设置等
循环
将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件
重复运行次数
循环次数事先已知
循环次数事先未知
常见的循环的命令:for, while, until
格式1:
for NAME [in WORDS ... ] ; do COMMANDS; done
for 变量名 [ in 列表 ];do
循环体
done
for 变量名 [ in 列表 ]
do
循环体
done
执行机制:
依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
for循环列表生成方式:
直接给出列表
整数列表:
{start..end}
$(seq [start [step]] end)
返回列表的命令:
$(COMMAND)
使用glob,如:*.sh
变量引用,如:$@,$*,$#
范例:面试题,计算1+2+3+...+100的结果
[root@centos8 ~]# sum=0;for i in {1..100};do let sum+=i;done ;echo sum=$sum
sum=5050
[root@centos8 ~]# seq -s+ 100 | bc5050
5050
范例
[root@centos8 ~]# cat /data/scripts/for_sum.sh
#!/bin/bash
sum=0
for i in $* ; do
let sum+=i
done
echo sum=$sum
[root@centos8 ~]# bash /data/scripts/for_sum.sh 1 2 3 4 5 6
sum=21
范例: 九九乘法表
#!/bin/bash
for i in {1..9};do
for j in `seq $i` ;do
echo -e "${j}x${i}=$[i*j]\t\c"
done
echo
done
生产案例:将指定目录下的所有文件的后缀改名为 bak 后缀
[root@centos8 ~]# cat /data/scripts/for_rename.sh
#!/bin/bash
DIR=/data/test
cd $DIR
for FILE in * ;do
PRE=`echo $FILE | sed -nr 's/(.*)\.([^.]+)$/\1/p'`
# SUFFIX=`echo $FILE | sed -nr 's/(.*)\.([^.]+)$/\2/p'`
mv $FILE $PRE.bak
done
范例:M37期面试题,要求将目录YYYY-MM-DD/中所有文件,移动到YYYY-MM/DD/下
#1 yyyy-mm-dd10.sh 创建YYYY-MM-DD,当前日期一年前365天到目前共365个目录,里面有10个文件,$RANDOM.log
[root@centos8 ~]# cat for_dir.sh
#!/bin/bash
for i in {1..365};do
DIR=`date -d "-$i day" +%F`
mkdir /data/test/$DIR -pv
cd /data/test/$DIR
for n in {1..10};do
touch $RANDOM.log
done
done
#2 移动到YYYY-MM/DD/下
#!/bin/bash
DIR=/data/test
cd $DIR
for DIR in * ;do
YYYY_MM=`echo $DIR | cut -d"-" -f1,2`
DD=`echo $DIR | cut -d'-' -f3`
[ -d $YYYY_MM/$DD ] || mkdir -p $YYYY_MM/$DD &> /dev/null
mv $DIR/* $YYYY_MM/$DD
done
rm -rf $DIR/*-*-*
面试题:扫描一个网段:10.0.0.0/24,判断此网段中主机在线状态,将在线的主机的IP打印出来
[root@centos8 ~]# cat /data/scripts/for_scan_host.sh
#!/bin/bash
NET=10.0.0
for ID in {1..254};do
{
ping -c1 -W1 $NET.$ID &> /dev/null && echo $NET.$ID is up || echo $NET.$ID is down
}&
done
wait
格式 2
双小括号方法,即((…))格式,也可以用于算术运算,双小括号方法也可以使bash Shell实现C语言风格的变量操作
I=10;((I++))
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done
说明:
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断
范例:
#!/bin/bash
for((sum=0,i=1;i<=100;sum+=i,i++));do
true
done
echo $sum
范例:九九乘法表
#!/bin/bash
#语法 1 实现
for i in {1..9};do
for j in `seq $i`; do
echo -e "${j}x${i}=$((j*i))\t\c"
done
echo
done
#语法 2 实现
for((i=1;i<10;i++)); do
for((j=1;j<=i;j++)); do
echo -e "${j}x$i=$((j*i))\t\c"
done
echo
done
范例:等腰三角形
[root@centos8 scripts]# cat for_triangle.sh
#!/bin/bash
read -p "请输入三角形的行数:" line
for((i=1;i<=line;i++));do
for((k=0;k<=line-i;k++));do
echo -e ' \c'
done
for((j=1;j<=2*i-1;j++));do
echo -e '*\c'
done
echo
done
范例:生成进度
[root@centos8 ~]# for ((i=0;i<=100;++i)); do printf "\e[4D%3d%%" $i; sleep 0.1s; done
练习:用 for 实现
1、判断/var/目录下所有文件的类型
2、添加10个用户user1-user10,密码为8位随机字符
3、/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K开头的输出为文件加stop,以S开头的输出为文件名加start,如K34filename stop S66filename start
4、编写脚本,提示输入正整数n的值,计算1+2+…+n的总和
5、计算100以内所有能被3整除的整数之和
6、编写脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态
7、打印九九乘法表
8、在/testdir目录下创建10个html文件,文件名格式为数字N(从1到10)加随机8个字母,如:1AbCdeFgH.html
9、打印等腰三角形
10、猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,只剩下一个桃子了。求第一天共摘了多少?