shell脚本:循环

一、for循环语句

1、语法结构

for 变量名 in 取值列表
do 
    命令序列
done

# 变量名:对应取值列表,若变量在取值列表中取值完成后循环结束
# 取值列表:for语句的执行条件,其中包括多个属性相同的对象,可选

2、应用实例
(1)打印1-5五个数字

[root@xxx for]# cat test01.sh 
#!/bin/bash
for i in {1..5}
 do
	echo $i
 done
[root@xxx for]# sh test01.sh 
1
2
3
4
5

# {1…5}表示范围1-5,for循环五次退出

(2)打印五次hello

[root@xxx for]# cat test02.sh 
#!/bin/bash
for i in {1..5}
 do 
	echo hello
 done
[root@xxx for]# sh test02.sh 
hello
hello
hello
hello
hello

# 注意:虽然我们定义了一个变量i,但是没有使用它,它只是控制循环次数。

(3)打印abcde

[root@xxx for]# cat test03.sh 
#!/bin/bash
for i in a b c d e
do 
	echo $i
done
[root@xxx for]# sh test03.sh 
a
b
c
d
e

# 也可以在for循环的范围使用abcde这种表达

(4)输出0-20之间的偶数

[root@xxx for]# cat test04.sh 
#!/bin/bash
for i in {0..20..2}
do
	echo $i
done
[root@xxx for]# sh test04.sh 
0
2
4
6
8
10
12
14
16
18
20

# {0…20…2} …2表示步长为2,每隔两个,即每次循环的数为+2:0+2,2+2…

花括号{}和seq在for循环的应用:
for i in {1…50…2} 1-50的奇数
for i in {2…50…2} 1-50的偶数
for i in {10…1} 1-10倒序排列
for i in $(seq 10) 1-10正序排列
for i in $(seq 10 -1 1) 1-10倒叙排列(-1代表无限,上限,最大值,1表示起始)
for i in $(seq 1 2 10) 1-10的奇数,中间为步长
for i in $(seq 0 2 10) 0-10的偶数,中间为步长
{1…5}=seq 5

不带列表循环执行时由用户指定参数和参数的个数决定的:

for 变量名
do
	command
done

(5)打印1-10的奇数

[root@xxx for]# cat test05.sh 
#!/bin/bash
for ((i=1;i<=10;i+=2))
do
	echo $i
done
[root@xxx for]# 
[root@xxx for]# sh test05.sh 
1
3
5
7
9

# ((i=1;i<=10;i+=2)) i起始值为1,最后一次循环的i值为小于等于10;每次循环i+2

(6)计算1-10的奇数和
sum=0定义一个变量
((i=1;i<=10;i+=2)) 循环奇数1.3…
let sum=i + i+i+sum 这么定义每次循环的奇数为i ,之前的循环奇数和定义为 i,之前的循环奇数和定义为i,之前的循环奇数和定义为sum
最后输出的$sum为 1-10的奇数和

(7)根据IP检测主机状态
文本查看
  创建一个包含ip地址的文本,设为变量,脚本会依次读取文本中ip地址循环
$ip为脚本中每个被读取的ip

[root@xxx for]# cat test07.sh 
#!/bin/bash
host=`cat /opt/host.txt`
for ip in $host
do
ping -c 3 -i 0.2 -W 2 $ip &> /dev/null
if [ $? -eq 0 ];then
   echo "host $ip is up"
else
   echo "host $ip is down"
fi
done
[root@xxx for]# sh test07.sh 
host 192.168.28.2 is up
host 192.168.28.10 is up
host 192.168.28.100 is down
host 192.168.28.222 is down
host baidu.com is up

网段查看
  可以选择某个网段查看主机状态,如想要看到输出过程,可创建一个文本而不注入黑洞文件/dev/null;而up和down状态分别注入不同文件去查看

[root@xxx for]# cat test07.sh 
#!/bin/bash
#host=`cat /opt/host.txt`
for ip in `seq 10`
do
ping -c 1 -i 0.2 -W 2 192.168.28.$ip &> /dev/null
if [ $? -eq 0 ];then
   echo "host $ip is up"
else
   echo "host $ip is down"
fi
done
[root@xxx for]# sh test07.sh 
host 1 is down
host 2 is up
host 3 is down
host 4 is down
host 5 is down
host 6 is down
host 7 is down
host 8 is down
host 9 is down
host 10 is up

(8)幸运会员
  expr $[ RANDOM%3+1 ] 输出1-3的随机数

[root@xxx opt]# cat test08.txt | grep 2 | awk -F: '{print $2}'
[root@xxx opt]# cat test08.txt 
1:zhangsan
2:lisi
3:wangwu

查看name.txt文件中的第二行,并以:为分割的第二个位置变量(注意使用’'是$2变量没有其他意义);以次来取出人名

[root@xxx for]# cat test08.sh 
#!/bin/bash
a=0
b=0
c=0
for ((i=1;i<=10;i++))
do
 num=$(expr $[RANDOM%3+1])
 name=$(cat /opt/name.txt | grep $num | awk -F: '{print $2}')
 case $name in
	zhangsan)
	let a++
	;;
	lisi)
	let b++
	;;
	wangwu)
	let c++
	;;
 esac
 echo "第$i轮选中的是$name"
done
  echo "zhangsan:$a次;lisi:$b次;wangwu:$c次"
[root@xxx for]# sh test08.sh 
第1轮选中的是wangwu
第2轮选中的是lisi
第3轮选中的是lisi
第4轮选中的是lisi
第5轮选中的是lisi
第6轮选中的是zhangsan
第7轮选中的是wangwu
第8轮选中的是zhangsan
第9轮选中的是lisi
第10轮选中的是zhangsan
zhangsan:3次;lisi:5次;wangwu:2次

(9)数字炸弹游戏
  数字炸弹游戏Ⅰ: 要求在1-100内定义一个数字,与用户交互,要求,每次提醒用户,数字猜大了还是猜小了,直到猜中为止,最后统计猜的次数,最多猜20次

[root@xxx for]# cat test09.sh 
#!/bin/bash
a=$(expr $[RANDOM%50+1])
b=0
for ((i=1;i<=20;i++))
do
read -p "请输入一个(1-50)之间的数字:" num
  let b++
   if [ $num -gt $a ];then
    echo "你输入的数字大了"
     elif [ $num -lt $a ];then
       echo "你输入的数字小了"
        elif [ $num -eq $a ];then
         echo "你对了"
echo "你一共猜了$b次"
exit
   fi
done
[root@xxx for]# sh test09.sh 
请输入一个(1-50)之间的数字:25
你输入的数字小了
请输入一个(1-50)之间的数字:30
你输入的数字大了
请输入一个(1-50)之间的数字:27
你对了
你一共猜了3次

猜对了后面使用exit或者break退出循环,不然会一直循环下去,continue退出本次循环。

二、while循环语句

1、语法结构

while 条件测试操作
do 
  命令序列
done

主要适用于要求控制循环次数、操作对象按数字顺序编号、按特定条件执行重复操作等情况。

2、应用实例
(1)打印1-5

[root@xxx while]# cat test01.sh 
#!/bin/bash
i=1
while [ $i -le 5 ]
do
 echo "$i"
  let i++
done
[root@xxx while]# sh test01.sh 
1
2
3
4
5

# 如果不用let i++会死循环

(2)猜数字,猜不对一直猜

[root@xxx while]# cat test02.sh 
#!/bin/basjh
num=$(expr $[RANDOM%30+1])
while true
do
 read -p "请输入1-30的一个数:" shu
 if [ $shu -eq $num ];then
  echo "你猜对了"
  break
  elif [ $shu -gt $num ];then
   echo "你猜大了"
  elif [ $shu -lt $num ];then
   echo "你猜小了"
 fi
done
[root@xxx while]# sh test02.sh 
请输入1-30的一个数:20
你猜大了
请输入1-30的一个数:15
你猜大了
请输入1-30的一个数:10
你猜大了
请输入1-30的一个数:5
你猜大了
请输入1-30的一个数:2
你猜小了
请输入1-30的一个数:1
你猜小了
请输入1-30的一个数:4
你猜对了

(3)输出1-100之间不能被3整除的数字

[root@xxx while]# cat test03.sh 
#!/bin/bash
i=1
while [ $i -le 100 ]
do
 if [[ $i%3 -ne 0 ]];then
  echo "$i"
 fi
let i++
done

(4)猜数字

[root@xxx while]# cat test04.sh 
#!/bin/basjh
num=$(expr $[RANDOM%30+1])
a=0
while true
do
 read -p "请输入1-30的一个数:" shu
 let a++
 if [ $shu -eq $num ];then
  echo "你猜对了"
  break
  elif [ $shu -gt $num ];then
   echo "你猜大了"
  elif [ $shu -lt $num ];then
   echo "你猜小了"
 fi
done
echo "你一共猜了$a次"
[root@xxx while]# sh test04.sh 
请输入1-30的一个数:15
你猜小了
请输入1-30的一个数:20
你猜小了
请输入1-30的一个数:23
你猜小了
请输入1-30的一个数:25
你猜小了
请输入1-30的一个数:27
你猜对了
你一共猜了5次

(5)批量添加规律编号用户

[root@xxx while]# cat test05.sh 
#!/bin/bash
users="students"
i=1
while [ $i -le 10 ]
do
useradd ${users}$i
echo "123456" | passwd --stdin ${user}$i &> /dev/null
let i++
done

(6)猜商品价格(0-99)

[root@xxx while]# cat test06.sh 
#!/bin/bash
a=$(expr $[RANDOM%100])
b=0
while true
read -p "请输入价格(0-100):" jiage
do
let b++
 if  [ $jiage -eq $a ];then
  echo "猜对了"
   exit
elif [ $jiage -gt $a ];then
  echo "你猜大了"
   else 
    echo "你猜小了"
 fi
done
       echo "你一共猜了$b次"
[root@xxx while]# sh test06.sh 
请输入价格(0-100):50
你猜大了
请输入价格(0-100):40
你猜大了
请输入价格(0-100):30
你猜大了
请输入价格(0-100):20
你猜大了
请输入价格(0-100):10
你猜大了
请输入价格(0-100):1
你猜小了
请输入价格(0-100):5
你猜小了
请输入价格(0-100):7
你猜小了
请输入价格(0-100):8
你猜小了
请输入价格(0-100):9
猜对了

(7)统计消费价格
  首先要求有4家店,每家店 3个商品(3个商品的价格统一为100 200 300),然后要求以交互式的方式,让用户选择进入哪家店,并且选择哪个商品(用户如果进入商店,假设必定至少会买一件),最后统计此次消费价格。

[root@xxx sh]# cat test07.sh 
#!/bin/bash
i=1
sum=0
while [ $i -lt 5 ]
do
 echo "进入第$i家店"
 read -p "是否进入看看(yes/no):" ask
 while [ $ask = "yes" ]
  do
echo "1.衣服100块
2.鞋子200块
3.手套50块
4.裤子150块"
 read -p "您需要哪件商品:" num
 case $num in
1)
echo "购买衣服成功"
expr $[sum+=100] &> /dev/null
;;
2)
echo "购买鞋子成功"
expr $[sum+=200] &> /dev/null
;;
3)
echo "购买手套成功"
expr $[sum+=50] &> /dev/null
;;
*)
echo "购买裤子成功"
expr $[sum+=150] &> /dev/null
;;
 esac
read -p "是否继续购买(yes/no):" ask
done
 let i++
if [ $ask = "no" ]
then
continue
fi
done
echo "今日消费$sum,牛蛙"
[root@xxx sh]# sh test07.sh 
进入第1家店
是否进入看看(yes/no):no
进入第2家店
是否进入看看(yes/no):no
进入第3家店
是否进入看看(yes/no):no
进入第4家店
是否进入看看(yes/no):no
今日消费0,牛蛙
[root@xxx sh]# sh test07.sh 
进入第1家店
是否进入看看(yes/no):yes
1.衣服100块
2.鞋子200块
3.手套50块
4.裤子150块
您需要哪件商品:1
购买衣服成功
是否继续购买(yes/no):no
进入第2家店
是否进入看看(yes/no):no
进入第3家店
是否进入看看(yes/no):no
进入第4家店
是否进入看看(yes/no):no
今日消费100,牛蛙

(8)三角形
  外循环定义行数,内循环定义输出几个*
echo -n “* ” -n不换行,如果换行的话会输出竖排的*,*后面有个空格看起来更舒服

[root@xxx sh]# cat test08.sh 
#!/bin/bash
for ((i=1;i<=$1;i++))
do
 for ((j=1;j<=$i;j++))
  do
   echo -n "* "
done
 echo
done
[root@xxx sh]# sh test08.sh 4
* 
* * 
* * * 
* * * * 

(9)倒三角

[root@xxx sh]# cat test09.sh 
#!/bin/bash
for ((i=$1;i>=1;i--))
do
  for ((j=1;j<=i;j++))
  do
   echo -n "* "
done
echo
done
[root@xxx sh]# sh test09.sh 4
* * * * 
* * * 
* * 
* 

(10)99乘法表

[root@xxx sh]#cat test10.sh 
#!/bin/bash
for ((i=1;i<=9;i++))
do
 for ((j=1;j<=i;j++))
  do
  echo -n "$i * $j = $(expr $i \* $j) "
   if [ $j -eq $i ];then
    echo -e "\n"
   fi
  done
done
[root@xxx sh]#sh test10.sh 
1 * 1 = 1 

2 * 1 = 2 2 * 2 = 4 

3 * 1 = 3 3 * 2 = 6 3 * 3 = 9 

4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16 

5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25 

6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36 

7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49 

8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64 

9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81 

三、until循环语句

1、语法结构

until 条件测试操作
do
	命令序列
done

until循环语句和while语句用法相反,while以true作为条件,而until以false作为条件。

2、应用实例
(1)计算1-50的和的写法

[root@xxx until]#cat test.sh 
#!/bin/bash
i=0
sum=0
until [ $i -eq 51 ]
 do
  let sum+=i
  let i++
 done
echo $sum
[root@xxx until]#sh test.sh 
1275

四、continue、break与exit

1、continue
  继续,但不会执行循环体内下面得代码,开始重新下一次循环。

应用实例:
打印1-5得数字,3不打印

[root@xxx for]#cat continue.sh 
#!/bin/bash
for ((i=1;i<=5;i++))
do
 if [ $i -eq 3 ];then
  continue
  else
  echo $i
 fi
done
[root@xxx for]#sh continue.sh 
1
2
4
5

输出结果为1245,3不输出,因为continue跳出后面的echo语句执行下一次循环了

2、break
  打断,马上停止本次循环,执行循环体外得代码

应用实例:
1-10得数字,7后面得都不打印

[root@xxx for]#cat break.sh 
#!/bin/bash
for ((i=1;i<=10;i++))
do
 if [ $i -eq 8 ];then
  break
  else
  echo $i
 fi
done
[root@xxx for]#sh break.sh 
1
2
3
4
5
6
7

3、exit
  直接跳出程序,后面跟返回状态码

应用实例:

[root@xxx for]#cat exit.sh 
#!/bin/bash
for i in {1..5}
do
 if [ $i -eq 3 ];then
  exit 21
 else
  echo $i
 fi
done
echo hi
[root@xxx for]#sh exit.sh 3
1
2
[root@xxx for]#echo $?
21

直接跳出程序所以不会执行echo hi,并通过echo $?返回码21查看

五、IFS字段分隔符

IFS是shell脚本中的一个重要概念,在处理文本数据时,它是相当有用的。IFS可以是White Space(空白键)、Tab( 表格键)、Enter( 回车键)中的一个或几个。

附录:

IFS字段分隔符参考自:
《IFS》
《Linux中shell的循环语句》

文中应用实例参考自:
《shell之循环语句》

你可能感兴趣的:(Linux,linux,bash,运维)