在Shell脚本应用中,常见的for循环采用遍历式、列表式的执行流程,通过指定变量从值列表中循环赋值,每次复制后执行固定的一组操作。
for 变量名 in 值列表 #可以是数值、字母,以空格隔开
do
命令序列
done
for 变量名 in {1..5} #{起始值~末尾值}==>1 2 3 4 5
do
命令序列
done
for 变量名 in `seq 5` #用于以指定增量从首数开始打印数字到尾数,即产生从某个数到另外一个数之间的所有整数
do
命令序列
done
for 变量名 in `ls /etc/*.conf` #读取文件内容
do
命令序列
done
#A:
#!/bin/bash
#循环打印出reve
a=10
for i in 1 2 3
do
echo "reve"
done
-----------------------------------------------
[root@reve shell]# bash test.sh #A: 结果
reve
reve
reve
#B:
#!/bin/bash
#循环打印出reve
a=10
for i in {1..3}
do
echo "reve"
done
-----------------------------------------------
[root@reve shell]# bash test.sh #B: 结果
reve
reve
reve
------------------------------------------------
#C:
#!/bin/bash
#循环打印出reve
a=10
for i in `seq $a` #seq命令用于以指定增量从首数开始打印数字到尾数,即产生从某个数到另外一个数之间的所有整数,并且可以对整数的格式、宽度、分割符号进行控制,
#在这里的 `seq $a` 表示:1 2 3 4 5
do
echo "reve"
done
[root@reve shell]# bash test.sh #C: 结果
reve
reve
reve
reve
reve
reve
reve
reve
reve
reve
---------------------------------------------
for((初值;条件;步长控制))
do
命令序列
done
注意ping命令可以测试某台主机的连通性,
使用-c选项可以设置ping的次数,
使用-i选项可以设置多次ping之间的间隔时间(单位秒),
使用-W选项可以设置ping不通时的超时时间(单位秒)。
#!/bin/bash
#利用循环ping 一个网段,有多少台主机可以ping通
for i in {40..50} #由于我的主机的IP是49,所以我就缩小范围,节省时间。
do
ping -c 3 -i 0.2 -W 1 192.168.4.$i &> /dev/null #输出结果给丢弃掉
if [ $? -eq 0 ];then #判断上一条语句的是否ping通,通就说明,执行成功,#? 返回 0.反之$? 返回 1
echo " 192.168.4.$i 通了"
let a++ #通了,就子增 + 1
else
echo " 192.168.4.$i 不通"
let b++ #不通也自增 + 1
fi
done
echo "有$a 台主机通了" #统计最后的结果
echo "有$b 台主机不通"
---------------------------------------------------
[root@reve shell]# vim Ping_color.sh
[root@reve shell]# bash Ping_color.sh
192.168.4.45 不通
192.168.4.46 不通
192.168.4.47 不通
192.168.4.48 不通
192.168.4.49 通了
192.168.4.50 不通
有1 台主机通了
有5 台主机不通
[root@reve shell]# vim Ping_color.sh
[root@reve shell]# bash Ping_color.sh
192.168.4.45 不通
192.168.4.46 不通
192.168.4.47 不通
192.168.4.48 不通
192.168.4.49 通了
192.168.4.50 不通
有1 台主机通了
有5 台主机不通
#!/bin/bash
#一次性创建10个账户
for i in {1..10}
do
useradd user$i
done
----------------------------
[root@reve shell]# bash Create_user.sh #创建用户成功,是不会有提示信息的
[root@reve shell]# bash Create_user.sh
useradd:用户“user1”已存在
useradd:用户“user2”已存在
useradd:用户“user3”已存在
useradd:用户“user4”已存在
useradd:用户“user5”已存在
useradd:用户“user6”已存在
useradd:用户“user7”已存在
useradd:用户“user8”已存在
useradd:用户“user9”已存在
useradd:用户“user10”已存在
#但是这个脚本存在一些问题,用户名写死了,不符合实际情况
-----------------------------
#我们可以让for循环读取文件的内容,例如读取员工信息表。按照里面的名字来创建名字
[root@reve shell]# cat /root/user #创建这份文件,文件内容是用户名
zhangsan
lisi
wangwu
reve
dingren
#!/bin/bash
#读取文件中的用户名,创建用户
for i in `cat /root/user` #让for循环读取这份文件
do
useradd $i
done
---------------------------------------
[root@reve shell]# bash Create_user.sh
[root@reve shell]# bash Create_user.sh
useradd:用户“zhangsan”已存在
useradd:用户“lisi”已存在
useradd:用户“wangwu”已存在
useradd:用户“reve”已存在
useradd:用户“dingren”已存在
[root@reve shell]# vim Create_user.sh
while循环属于条件式的执行流程,会反复判断指定的测试条件,只要条件成立即执行固定的一组操作,直到条件变化为不成立为止。所以while循环的条件一般通过变量来进行控制,在循环体内对变量值做相应改变,以便在适当的时候退出,避免陷入死循环。
while 条件测试 #没有冒号 “ : ” 但是有空格
do
命令序列
done
while : #有空格
do
命令序列
done
#!/bin/bash
whlie : #条件永远成立 ==死循环
do
echo "abc"
done
执行这样的脚本和会让机器陷入死循环,会消耗大量的CPU资源,如下图片。
我用一台虚拟机执行这样程序,这里可以看到我的一个CPU资源已经达到了100%。这样长期执行这样的脚本,会对机器造成很大影响。所以我们在执行while循环,需注意避免进入这样的死循环。
#!/bin/bash
#利用while循环猜一个数字
Num=$[RANDOM% 100 + 1] #随即生成一个数,这个值不参与while循环当中。
b=0
while :
do
let b++ #需要提前对b进行初始化复为0
read -p "请输入一个数字(1~100):" a #从键盘上读取一个值
if [ $a -eq $Num ];then
echo "你猜对了,总计:猜了$b次"
exit 2 #猜对了就退出,避免进入死循环
elif [ $a -gt $Num ];then
echo "你猜大了"
else
echo "你猜小了"
fi
done
#!/bin/bash
i=1
while [ $i -le 254 ] # <= 254
do
IP="192.168.4.$i"
ping -c 3 -i 0.2 -W 1 $IP &> /dev/null
if [ $? -eq 0 ] ; then
echo "Host $IP is up."
else
echo "Host $IP is down."
fi
let i++
done
case分支属于匹配执行的方式,它针对指定的变量预先设置一个可能的取值,判断该变量的实际取值是否与预设的某一个值相匹配,如果匹配上了,就执行相应的一组操作,如果没有任何值能够匹配,就执行预先设置的默认操作。
case 变量 in
模式1) #同时模式1)后面有个“)”
命令序列1 ;; #需要注意:格式必须是两个分号
模式2)
命令序列2 ;;
.. ..
*) # * 表示默认匹配
默认命令序列
esac
#!/bin/bash
#测试case
case $1 in #位置变量$1和下面的字符进行匹配,并执行对应的序列
t)
touch $2 ;; # $2 输入我们创建的文件名
v)
touch $2 ;;
c)
touch $2 ;;
*)
echo "t|v|c"
esac
---------------------------------------
#拓展:我们可以利用管道 | 来实现区分大小写的功能。或者误操作情况。可以自定义:
case $1 in #位置变量$1和下面的字符进行匹配,并执行对应的序列
t|T|tt)
touch $2 ;; # $2 输入我们要
v)
touch $2 ;;
c|C) #匹配大写C和小写C都可以执行下面的命令序列
touch $2 ;;
*)
echo "t|v|c"
esac
------------------------------
#测试结果
[root@reve shell]# bash case_test.sh t /opt/case_test
[root@reve shell]# bash case_test.sh t /opt/case_test
什么是函数:
- 在shell环境中,将一些需要重复性的操作,定义为公共的语句块,即可称为函数
使用函数的好处
- 使脚本代码更加简洁,增强易读性
- 提高shell脚本的执行效率
服务脚本中的函数应用
-适用与比较复杂的启动/终止控制哦操作
-方便在需要时多次调用
#格式1:
function 函数名 {
命令序列
.. ..
}
---------------------------------
格式2:类似C语言风格
函数名() {
命令序列
.. ..
}
[root@reve shell]# A(){
> mkdir bbbb
> touch aaaa.txt
> }
[root@reve shell]# type A #type(用来显示指定命令的类型) 可以查看A是否为函数
A 是函数
A ()
{
mkdir bbbb;
touch aaaa.txt
}
[root@reve shell]# type B
-bash: type: B: 未找到
[root@reve shell]# A
[root@reve shell]# ls
bbbb aaaa.txt
[root@reve shell]#
#注意:我们一般写函数,不写在终端,一般写在shell脚本当中。
[root@reve shell]# echo -e "\033[033mABC\033[0m" #修改字体颜色
ABC #橙色
[root@reve shell]# echo -e "\033[024mABC\033[0m"
ABC #蓝色
#注意!!!:echo -e(必须带-e); \033[ :是固定格式。
# !!修改字体颜色后,的还原初始化颜色转态,以免造成麻烦。
# !!\033[0m : 还原初始化颜色
#!/bin/bash
#一个修改字体颜色的函数
Change_color(){
echo -e "\033[$1m$2\033[0m"
}
Change_color 31 REVE
Change_color 32 REVE
Change_color 33 REVE
Change_color 34 REVE
Change_color 35 REVE
Change_color 36 REVE
Change_color 37 REVE
Change_color 38 REVE
-------------------------------------
#结果
[root@reve shell]# vim Change_color.sh
[root@reve shell]# bash Change_color.sh
REVE #红色
REVE #绿色
REVE #橙色
REVE #蓝色
REVE #粉色
REVE #浅蓝色
REVE #灰色
REVE #黑色
[root@reve shell]#
我们可以利用我们刚才的代码,来实现
[root@reve shell]# vim Ping_color.sh
#!/bin/bash
#利用循环ping 一个网段,有多少台主机可以ping通
Change_color(){
echo -e "\033[$1m$2\033[0m"
}
for i in {45..50} #由于我的主机的IP是49,所以我就缩小范围,节省时间。
do
ping -c 3 -i 0.2 -W 1 192.168.4.$i &> /dev/null #输出结果给丢弃掉
if [ $? -eq 0 ];then #判断上一条语句的是否ping通,通就说明,执行成功,#? 返回 0.反之$? 返回 1问题
Change_color 32 " 192.168.4.$i 通了"
let a++ #通了,就子增 + 1
else
Change_color 31 " 192.168.4.$i 不通"
let b++ #不通也自增 + 1
fi
done
echo "有$a 台主机通了" #统计最后的结果
echo "有$b 台主机不通"
测试结果
[root@reve shell]# bash Ping_color.sh
192.168.4.45 不通 #红色
192.168.4.46 不通 #红色
192.168.4.47 不通 #红色
192.168.4.48 不通 #红色
192.168.4.49 通了 #绿色
192.168.4.50 不通 #绿色
有1 台主机通了
有5 台主机不通
.(){ #定义一个名为 . 的函数
.|.& #在后台递归调用函数
}
. #再次调用函数
#注意:此操作非常危险,尽量在虚拟上使用。
#执行此脚本后,可以通过强制关机重启,即可恢复
通过break、continue、exit在Shell脚本中实现中断与退出的功能。
类型 | 作用 |
---|---|
break(中断) | 可以结束整个循环 |
continue(继续) | 结束本次循环,进入下一次循环 |
exit (退出) | 结束整个脚本 |
#continue
#!/bin/bash
for i in {1..6}
do
[$i -eq 4 ] && continue #当循环到4的时候,退出本次循环,继续下次循环
echo $i
done
echo hahaha
--------------------------
#效果
[root@reve shell]# bash Test_contiune.sh
1
2
3
5
6
hahaha
-------------------------------
#break
#!/bin/bash
for i in {1..6}
do
[$i -eq 4 ] && break #当循环到4的时候,退出本次循环
echo $i
done
echo hahaha
--------------------------
#效果
[root@reve shell]# bash Test_contiune.sh
1
2
3
hahaha
[root@reve shell]#
---------------------------
#exit
#!/bin/bash
for i in {1..6}
do
[$i -eq 4 ] && exit #当循环到4的时候,退出程序
echo $i
done
echo hahaha
--------------------------
[root@reve shell]# bash Test_contiune.sh
1
2
3
[root@reve shell]#
#!/bin/bash
#把用户输入的值进行求和,输入0则结束
sum=0
while : #利用while进行循环
do
read -p "请输入一组合数字,0结束" Num
[ $Num -eq 0 ] && break #把0作为判断条件
sum=$[Num + sum]
done
echo $sum
----------------------
#结果
[root@reve shell]# bash While_sum.sh
请输入一组合数字,0结束5
请输入一组合数字,0结束5
请输入一组合数字,0结束5
请输入一组合数字,0结束5
请输入一组合数字,0结束0
20
#!/bin/bash
#找出1~20以内6的倍数,并输出她的平方值
sum=0
Num=0
for i in {1..20}
do
Num=$[i % 6]
if [ $Num -eq 0 ];then
sum=$[i*i]
echo "6的倍数平方值为 $sum "
fi
done
----------------------
#结果
[root@reve shell]# bash six_sqrt.sh
6的倍数平方值为 36
6的倍数平方值为 144
6的倍数平方值为 324
#for 故障错误信息
#基本语法错误,
#for循环的执行,需要嵌入到do和doe中间
#使用case语句时,需要记住后面是以 ;; 结尾的
写的不好,请大家见谅哈