条件选择
🔣选择执行 if 语句
- 单分支
if 判断条件;then
条件为真的分支代码
fi
- 双分支
if 判断条件; then
条件为真的分支代码1
else
条件为假的分支代码2
fi
- 双分支
if 判断条件1; then
条件1为真的分支代码1
elif 判断条件2; then
条件2为真的分支代码2
…
else
以上条件都为假的分支代码N
fi
[root@CentOS /data/script]$ cat if_bmi.sh (#BMI指数测试脚本)
#!/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 -le 24 ];then
echo "身材标准,很棒"
else
echo "太胖了,得减肥了"
fi
[root@CentOS /data/script]$ bash if_bmi.sh
输入身高(m):1.58
输入体重(kg):59
身材标准,很棒
[root@CentOS /data/script]$ bash if_bmi.sh
输入身高(m):333
身高输入错误!
[root@CentOS /data/script]$ bash if_bmi.sh
输入身高(m):1
输入体重(kg):1222
体重输入错误!
[root@CentOS /data/script]$
🔣条件判断 case 语句
case 变量引用 in
PAT1)
分支1 ;;
PAT2)
分支2;;
…
*)
默认分支 ;;
esac
case支持glob风格的通配符:* 任意长度任意字符
? 任意单个字符
[] 指定范围内的任意单个字符
| 或者,如: a|b
[root@CentOS /data/script]$ cat lottery.sh (#抽奖脚本)
#!/bin/bash
read -p "输入数字:" INPUT
case $INPUT in
1|2|3)
echo "一等奖";;
4|5|6)
echo "二等奖";;
7|8|9)
echo "三等奖";;
*)
echo "谢谢参与";;
esac
[root@CentOS /data/script]$ bash lottery.sh
输入数字:3
一等奖
[root@CentOS /data/script]$ bash lottery.sh
输入数字:12
谢谢参与
[root@CentOS /data/script]$ cat yes-no.sh (#yes or no 脚本)
#!/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 will agree it";;
n|no)
echo "you will refuse it";;
*)
echo "you input wrong,please iput yes or no";;
esac
[root@CentOS /data/script]$ bash yes-no.sh
do you agree(yes/no):y
you will agree it
[root@CentOS /data/script]$ bash yes-no.sh
do you agree(yes/no):r
you input wrong,please iput yes or no
[root@CentOS /data/script]$ bash yes-no.sh
do you agree(yes/no):n
you will refuse it
练习
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循环
执行机制:依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
工作中可用for循环批量处理
格式1
- for NAME [in WORDS … ] ; do COMMANDS; done
for 变量名 [ in 列表 ];do
循环体<br />done
for 变量名 [ in 列表 ]
do
循环体
done
for循环列表生成方式:
- 直接给出列表
- 整数列表:
{start..end}
$(seq [start [step]] end)
- 返回列表的命令:
$(COMMAND)
- 使用glob,如:*.sh
- 变量引用,如:$@,$*,$#
```bash
范例:面试题,计算1+2+3+…+100的结果
[root@cent7 /data/script]$ sum=0;for i in {1..100};do let sum+=i;done;echo sum=$sum sum=5050 [root@cent7 /data/script]$ seq -s+ 100 |bc 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
九九乘法表
[root@cent7 /data/script]$ 99.sh
11=1
12=2 22=4
13=3 23=6 33=9
14=4 24=8 34=12 44=16
15=5 25=10 35=15 45=20 55=25
16=6 26=12 36=18 46=24 56=30 66=36
17=7 27=14 37=21 47=28 57=35 67=42 77=49
18=8 28=16 38=24 48=32 58=40 68=48 78=56 88=64
19=9 29=18 39=27 49=36 59=45 69=54 79=63 89=72 99=81
[root@cent7 /data/script]$ cat 9*9.sh
!/bin/bash
for r in {1..9};do
for c in seq "$r"
;do
echo -e “$c$r=$[$r$c]\t\c)”
done
echo
done
```bash
生产案例:将指定目录下的所有文件的后缀改名为 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/下
面试题:扫描一个网段:10.0.0.0/24(10.0.0.1---10.0.0.254),判断此网段中主机在线状态,将在线的主机的IP打印出来
#!/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++))
!/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@cent7 /data/script]$ tang.sh
请输入三角形的行数: 4
*
***
*****
*******
范例:生成进度
[root@centos8 ~]#for ((i = 0; i <= 100; ++i)); do printf "\e[4D%3d%%" $i;sleep 0.1s; done
练习
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天早上想再吃时,只剩下一个桃子了。求第一天共摘了多少?
🔣while循环
[root@cent7 /data/script]$ cat sum-while.sh
#!/bin/bash
sum=0
i=1
while [ $i -le 100 ] ;do
let sum+=$i
let i++
done
echo $sum
- 无限循环
while true; do
循环体
done
#配置发邮件的邮箱
[root@centos8 ~]#cat .mailrc
set from=29308620@qq.com
set smtp=smtp.qq.com
set smtp-auth-user=29308620@qq.com
set smtp-auth-password=esvnhbnqocirbicf
set smtp-auth=login
set ssl-verify=ignore
[root@centos8 ~]#cat while_diskcheck.sh
#!/bin/bash
WARNING=80
while :;do (#冒号表示true,表示无限循环)
USE=`df | sed -rn '/^\/dev\/sd/s#.* ([0-9]+)%.*#\1#p' |sort -nr|head -n1`
if [ $USE -gt $WARNING ];then
echo Disk will be full from `hostname -I` | mail -s "disk warning" 29308620@qq.com
fi
sleep 10
done
练习
1、编写脚本,求100以内所有正奇数之和
2、编写脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态,并统计在线和离线主机各多少
3、编写脚本,打印九九乘法表
4、编写脚本,利用变量RANDOM生成10个随机数字,输出这个10数字,并显示其中的最大值和最小值
5、编写脚本,实现打印国际象棋棋盘
6、后续六个字符串:efbaf275cd、4be9c40b8b、44b2395c46、f8c8873ce0、b902c16c8b、ad865d2f63是通过对随机数变量RANDOM随机执行命令: echo $RANDOM|md5sum|cut -c1-10 后的结果,请破解这些字符串对应的RANDOM值
🔣until循环
- until COMMANDS; do COMMANDS; done
- until CONDITION; do
循环体
done
(进入条件: CONDITION 为false; 退出条件: CONDITION 为true)
- 无限循环
🔣continue循环
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
while CONDITION1; do
CMD1
…
if CONDITION2; then
continue
fi
CMDn
…
done
[root@centos8 script40]#cat continue_for.sh
#!/bin/bash
for ((i=0;i<10;i++));do
for((j=0;j<10;j++));do
[ $j -eq 5 ] && continue 2
echo $j
done
echo ---------------------------
done
🔣break循环
break [N]:提前结束第N层整个循环,最内层为第1层
while CONDITION1; do
CMD1
…
if CONDITION2; then
break
fi
CMDn
…
done
[root@centos8 script40]#cat break_for.sh
#!/bin/bash
for ((i=0;i<10;i++));do
for((j=0;j<10;j++));do
[ $j -eq 5 ] && break
echo $j
done
echo ---------------------------
done
#********************************************************************
for ((i=0;i<10;i++));do
for((j=0;j<10;j++));do
[ $j -eq 5 ] && break 2
echo $j
done
echo ---------------------------
done
[root@centos8 script40]#bash break_for.sh
0
1
2
3
4
[root@centos8 script40]#cat menu.sh
#!/bin/bash
sum=0
COLOR='echo -e \033[1;31m'
COLOR2='echo -e \033[1;32m'
END="\033[0m"
while true;do
echo -e "\033[33;1m\c"
cat <<-EOF
1) 鲍鱼
2) 满汉全席
3) 龙虾
4) 燕窝
5) 帝王蟹
6) 退出
EOF
echo -e "\033[0m"
read -p "请点菜(1-6): " MENU
case $MENU in
1|4)
$COLOR'菜价: $10'$END
let sum+=10
;;
3|5)
$COLOR'菜价: $20'$END
let sum+=20
;;
2)
$COLOR'菜价: $1000'$END
let sum+=1000
;;
6)
$COLOR2"你点的菜总价格是:\$$sum"$END
break
;;
*)
echo "点错了,没有这道菜"
;;
esac
$COLOR2"你点的菜总价格是:\$$sum"$END
done
[root@centos8 script40]#cat guess.sh
#!/bin/bash
NUM=$[RANDOM%10]
while read -p "输入 0-9 之间的数字: " INPUT ;do
if [ $INPUT -eq $NUM ];then
echo "恭喜你猜对了!"
break
elif [ $INPUT -gt $NUM ];then
echo "数字太大了,重新猜!"
else
echo "数字太小了,重新猜!"
fi
done
🔣shift命令
shift [n] 用于将参量列表 list 左移指定次数,缺省为左移一次。
参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到shift
范例:doit.sh
#!/bin/bash
# Name: doit.sh
# Purpose: shift through command line arguments
# Usage: doit.sh [args]
while [ $You can't use 'macro parameter character #' in math mode# -gt 0 ] # or
(( $# > 0 ))
do
echo $*
shift
done
./doit.sh a b c d e f g h
范例:示例:shift.sh
#!/bin/bash
#step through all the positional parameters
until [ -z "$1" ]
do
echo "$1"
shift
done
echo
./shfit.sh a b c d e f g h
[root@centos8 ~]#vim shift_batch_user.sh
#!/bin/bash
if [ $# -eq 0 ];then
echo "Usage: ` basename $0` user1 user2 ..."
exit
fi
while [ "$1" ];do (#判断字符串不为空时)
if id $1 &> /dev/null;then
echo $1 is exist
else
useradd $1
echo "$1 is created"
fi
shift
done
echo "All user is created"
[root@centos8 script40]#bash shift_batch_user.sh tom alice jack
tom is exist
alice is exist
jack is created
All user is created
练习
1、每隔3秒钟到系统上获取已经登录的用户的信息;如果发现用户hacker登录,则将登录时间和主机记录于日志/var/log/login.log中,并退出脚本
2、随机生成10以内的数字,实现猜字游戏,提示比较大或小,相等则退出
3、用文件名做为参数,统计所有参数文件的总行数
4、用二个以上的数字为参数,显示其中的最大值和最小值
🔣while read特殊用法
while 循环的特殊用法,遍历文件或文本的每一行
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
说明:依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
[root@centos8 ~]#echo magedu | read X ; echo $X
[root@centos8 ~]#echo magedu | while read X ; do echo $X;done
magedu
[root@centos8 ~]#echo magedu | { read X ; echo $X; }
magedu
[root@centos8 ~]#echo magedu | ( read X ; echo $X )
magedu
[root@centos8 ~]#echo mage wang zhang | ( read X Y Z; echo $X $Y $Z )
mage wang zhang
[root@centos8 ~]#echo mage wang zhang | while read X Y Z; do echo $X $Y $Z;done
mage wang zhang
cat while_read_diskcheck.sh
#!/bin/bash
WARNING=80
MAIL=root@wangxiaochun.com
df |sed -nr "/^\/dev\/sd/s#^([^ ]+) .* ([0-9]+)%.*#\1 \2#p"|while read DEVICE
USE;do
if [ $USE -gt $WARNING ] ;then
echo "$DEVICE will be full,use:$USE" | mail -s "DISK WARNING" $MAIL
fi
done
#********************************************************************
cat while_read_check_dos.sh
#!/bin/bash
lastb | sed -rn '/ssh:/s@.* ([0-9.]{1,3}{3}[0-9]{1,3}) .*@\1@p'|sort |uniq -c
|while read count ip ;do
if [ $count -gt 3 ];then
iptables -A INPUT -s $ip -j REJECT
fi
done
范例:查看/sbin/nologin的shell类型的用户名和UID
cat while_read_passwd.sh
#!/bin/bash
while read line ;do
if [[ "$line" =~ /sbin/nologin$ ]] ;then
echo $line | cut -d: -f1,3
fi
done < /etc/passwd
范例:单词文件
[root@centos6 ~]#wc -l /usr/share/dict/linux.words
479829 /usr/share/dict/linux.words
🔣select循环与菜单
- select NAME [in WORDS … ;] do COMMANDS; done
- select variable in list ;do
循环体命令
done
select 循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准错误上,并显示 PS3 提示符,等待用户输入;
用户输入菜单列表中的某个数字,执行相应的命令;
用户输入被保存在内置变量 REPLY 中;
select 是个无限循环,因此要用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环;
select 经常和 case 联合使用;
与 for 循环类似,可以省略 in list,此时使用位置参量
cat select.sh
#!/bin/bash
sum=0
PS3="请点菜(1-6): "
select MENU in 北京烤鸭 佛跳墙 小龙虾 羊蝎子 火锅 点菜结束;do
case $REPLY in
1)
echo $MENU 价格是 100
let sum+=100
;;
2)
echo $MENU 价格是 88
let sum+=88
;;
3)
echo $MENU价格是 66
let sum+=66
;;
4)
echo $MENU 价格是 166
let sum+=166
;;
5)
echo $MENU 价格是 200
let sum+=200
;;
6)
echo "点菜结束,退出"
break
;;
*)
echo "点菜错误,重新选择"
;;
esac
done
echo "总价格是: $sum"