RHCE(第二部分)-----第五章:流程控制之循环

第五章、流程控制之循环

5.1 步进循环语句for

​ for循环是最简单,也是最常用的循环语句。与其他的程序设计语言一样,for循环都是初学者在学习循环结构时的入门课程。for循环通常用于遍历整个对象或者数字列表。按照循环条件的不同,for循环语句可以分为带列表的for循环、不带列表的for循环以及类C风格的for循环。本节将介绍这3种不同的for循环结构。

5.1.1 带列表的for循环语句

带列表的for循环通常用于将一组语句执行已知的次数,其基本语法如下

for variable in {list};do
   statement1
   statement2
   ...
done

​ 在上面的语法中,variable称为循环变量,list是一个列表,可以是一系列的数字或者字符串,元素之间使用空格隔开。do和done之间的所有的语句称为循环体,即循环结构中重复执行的语句。for循环体的执行次数与list中元素的个数有关。在带列表的for语句的执行时,Shell会将in关键字后面的list列表的第1个元素的值赋给变量variable,然后执行循环体;当循环体中的语句执行完毕之后,Shell会将列表中的第1个元素的值赋给变量variable,然后再次执行循环体。当list列表中的所有的元素都被访问后,for循环结构终止,程序将继续执行done语句后面的其他的语句。

示例:1:直接列出变量列表所有元素

方法1:直接列出元素方法

# cat for-1.sh 
#!/bin/sh
for IP in 192.168.1.101 192.168.1.102
do
    ping $IP &>/dev/null
    [ $? = 0 ] && echo  up || echo down
done

方法2:使用大括号
# cat for-2.sh 
#!/bin/sh
for IP in 192.168.1.10{1..5}
do
    echo $IP
done
-------------------------
for i in {1..100};do
	let sum+=i
	#sum=sum+i
done
echo "$1+2+3+4.."=$sum

方法3:使用seq   https://www.cnblogs.com/faberbeta/p/linux-shell007.html
# cat for-3.sh 
#!/bin/sh
for IP in $(seq -f "192.168.1.10%1g" 1 5)    192.168.1.1 192.168.1.2
do
    echo $IP
done

示例2:获取当前目录下的文件名作为变量列表打印输出

# cat for-4.sh 
#!/bin/sh
for FILE in $(ls -F | grep -v /$)
do
    echo $FILE
done
---------------------------------
for f in `ls` ;do
        if [ -d $f ];then
                echo $f
        fi
done

5.1.2 不带列表的for循环语句

​ 在某些特殊情况下,for循环的条件列表可以完全省略,称为不带列表的for循环语句。如果没有为for循环提供条件列表,Shell将从命令行获取条件列表。不带列表的for循环语句的一般语法如下:

for variable
do
   statement1
   statement2
   ... 
done

./f.sh `seq 10`

由于系统变量$@同样可以获取所有的参数,所以以上的语法等价于以下语法:

for variable in $@或$*
do
   statement1
   statement2
   ...
done 

示例:

[root@localhost ~]# cat f1.sh 
#! /bin/bash

#不带条件列表
for arg
do
   #输出每个参数
   echo "$arg"
done
[root@localhost ~]# sh f1.sh {1..6}
1
2
3
4
5
6

5.1.3 类C风格的for循环语句

for ((expression1;expression2;expression3))
do
   statement1;
   statement2;
   ...
done

​ 在上面的语法中,for循环语句的执行条件被2个圆括号包括起来。执行条件分为3个部分,由2个分号隔开,第1部分expression1通常时条件变量初始化的语句;第2部分expression2是决定是否执行for循环的条件。当expression2的值为0时,执行整个循环体;当expression2的值为非0时,退出for循环体。第3部分,即表达式expression3通常用来改变条件变量的值,例如递增或者递减等。

++i是先i自加1,然后在使用i的值
i++是先用i的值,在i自加1。
[root@localhost ~]# x=1
[root@localhost ~]# y=1
[root@localhost ~]# echo $((x++))
1
[root@localhost ~]# echo $((++y))
2

示例3:批量创建用户

要求:

用户名以test开头,按数字序号变化;

一共添加30个账号,即test01,tes02…,test30

用户初始密码为123456

思路:

用户0-9:
	useradd test01 test02
用户10-30
	useradd test
分析: 
    根据要求使用循环语句完成
    创建用户使用useradd命令,根据命名规则,10以下的需要加0
    初始账号设置方法(echo “123456” |passwd –stdin username)
示例代码:user01   user10
for ((i=1;i<=30;i++))
do
    if [ $i -lt 10 ]
    then
   	    user=test0$i
    else
    	user=test$i
    fi
    if ! id -u $user &> /dev/null
    then
    useradd $user
    echo "123456" | passwd --stdin $user &> /dev/null
    else
    echo "$user is exists..."
    fi
done


注意:可以简化写法,直接用for带列表的循环,这样就不用for里面嵌套if判断
比如for i in {01..30}

示例4:编写一个 Shell 程序,实现判断当前网络(假定为192.168.1.0/24,根据实际情况实现)里,当前在线用户的IP

分析:

笔试常考题目,使用循环
for ((i=1;i<=254;i++))
do
    if pint -c 2 -W 1 192.168.1.$i &>/dev/null
    then
        echo "192.168.1.$i is up..."
    else
        echo "192.168.1.$i is down..."
    fi
done

5.2 while循环语句

​ while循环是另外一种常见的循环结构。使用while循环结构,可以使得用户重复执行一系列的操作,直到某个条件的发生。这听起来好像跟until循环非常相似,但是与until语句相比,while语句有着较大的区别。本节将详细介绍while语句的使用方法。

while循环语句的基本语法如下:

while expression
do
    statement1
    statement2
    ...
done

​ 在上面的语法中,expression表示while循环体执行时需要满足的条件。虽然可以使用任意合法的Shell命令,但是,通常情况下,expression代表一个测试表达式。与其他的循环结构一样,do和done这2个关键字之间的语句构成了循环体。

5.2.1 while循环读取文件

方法一:采用exec读取文件,然后进入while循环处理(一般不使用该方法)
exec < File
while read line
do
    statement1
done

方法二:使用cat读文件,然后通过管道进入while循环处理
cat File | while read line
do
    statement1
done

方法三:通过在while循环结尾,使用输入重定向方式
while read line
do
    statement1
done < file
变量参数是按换行符分割

exec:

[root@localhost day05]# exec 命令    # 执行完该命令后退出

5.2.2 while语句的示例

示例1:猜商品价格 通过变量RANDOM获得随机数

提示用户猜测并记录次数,猜中后退出循环

分析:
    产生随机数
    猜中退出循环,显然要用死循环(while true),满足条件退出程序
    通过if条件判断,根据用户输入数值和生成随机数比较
    记录猜测次数,每猜测一次加1

通过系统环境变量($RANDOM)产生随机数
PRICE=$[$RANDOM % 100 ]
TIMES=0
while true
do
    read -p "Please enter the product price [0-99] : " INT
    let TIMES++
    if [ $INT -eq $PRICE ]
    then
        echo "Good luck,you guessed it."
        echo "You have guessed $TIMES times."
        exit 0
    elif [ $INT -gt $PRICE ]
    then
        echo "$INT is too high"
    else
               echo "$INT is too low"
    fi
done
----------------------------------------------------------------------------
利用RANDOM取随机数
shell有一个环境变量RANDOM,范围是0--32767%100
如果我们想要产生0-25范围内的数:$(($RANDOM%26)) 在$(()) 是可以省略取值的$符号的。(All tokens in the expression undergo parameter expansion, string expansion, command substitu-tion, and quote removal.)
用这个环境变量对26取模即可。
如果想得到1--68范围内的数 : $(($RANDOM%68+1 ))
如果想得到6--87范围内的数 : $(($RANDOM%82+6 ))
####### 猜值游戏:1-100
[root@localhost day05]# vim d.sh
p=$(($RANDOM%100+1))
while true;do
    read -p "请输入商品的价格(1-100):" price
    if [ $price -eq $p ];then
        echo "恭喜你猜对了,商品的价格为$price"
        break
    elif [ $price -lt $p ];then
        echo "猜小了,再来一次哦"
        continue
    else
        echo "猜大了,再来一次哦"
        continue
    fi
done
[root@localhost day05]# bash d.sh 
请输入商品的价格(1-100):50
猜大了,再来一次哦
请输入商品的价格(1-100):25
猜大了,再来一次哦
请输入商品的价格(1-100):12
猜小了,再来一次哦
请输入商品的价格(1-100):20
猜大了,再来一次哦
请输入商品的价格(1-100):18
恭喜你猜对了,商品的价格为18

示例2:while读取文件

工作过程中遇到要从一个ip列表中获取ip port然后ssh ip 到目标机器进行特定的操作

# cat iplist 
192.168.147.101 5225 
192.168.147.102 2234
192.168.147.103 4922

# cat while-read.sh 
#!/bin/sh

while read line
do
    IP=$(echo $line |awk '{print $1}')
    PORT=$(echo $line |awk '{print $2}')
    echo "IP: $IP, PORT: $PORT"
done <iplist

示例3:将之前用for语句创建的test01-test30用户删除

i=1
while [ $i -le 30 ]
do
    if [ $i -le 9 ]
    then
        user=test0$i
    else
    user=test$i
    fi

    if id -u $user &>/dev/null
    then
    userdel -r $user
    else
    echo "$user is not exists..."
    fi

    let i++
done

注意:while判断变量也可以使用(()),比如while ((i<=30))

5.2.3 until循环语句

​ until循环语句同样也存在于多种程序设计语言中。顾名思义,until语句的作用时将循环体重复执行,直到某个条件成立为止。恰当地使用until语句,可以收到事半功倍地效果。本节将详细介绍until语句的使用方法。

​ until循环语句的功能是不断地重复执行循环体中的语句,直至某个条件成立。until语句的基本语法如下:

until expression
do
   statement1
   statement2
   ...
done

​ 在上面的语法中,expression是一个条件表达式。当该表达式的值不为0时,将执行do和done之间的语句;当expression的值为0时,将退出until循环结构,继续执行done语句后面的其它的语句。

示例:将之前用for语句创建的test01-test30用户删除

i=1
until [ $i -gt 30 ]
do
    if [ $i -le 9 ]
    then
        user=test0$i
    else
    user=test$i
    fi

    if id -u $user &>/dev/null
    then
    userdel -r $user
    else
    echo "$user is not exists..."
    fi

    let i++
done

5.2.4 select循环语句

​ select循环语句的主要功能是创建菜单,在执行带有select循环语句脚本时,输出会按照数字顺序的列表显示一个菜单,并显示提示符(默认是#?),同时等待用户输入数字选择。select语句的基本语法如下:

select 变量名 [ in 菜单值列表 ]
do
   statement1
   statement2
   ...
done

示例:

#!/bin/bash
select mysql_version in 5.1 5.6
do
    echo $mysql_version
done
# bash test.sh
1) 5.1
2) 5.6:
#? 1
5.1
#? 2
5.6
--------------------------------------------------
i=0
while [ $i -lt  3 ];do
    select  version in 1.2 2.2 3.2 ;do
        echo $version
        break
    done
    let i++
done

5.3 嵌套循环

​ 在程序设计语言中,嵌套的循环也是一种非常常见的结构。Shell同样也支持嵌套循环。通过嵌套循环,可以完成更复杂的功能。本节将介绍Shell中嵌套循环的使用方法。

注意:校招常考题目。

示例1:打印九九乘法表

1*1=1 
1*2=2 2*2=4
1*3=3 2*3=6  3*3=9 
.....

#行  9  i=2
#列  ((j=1;j<=i;j++))  j=1 j=2
     1*1
     1*=2 2*2=4
     .....
     j*i=$((j*i))

## for循环
for i in  `seq 9`      #i循环次数    i=被乘数  
do
         for j in `seq 9`    #j乘数 ++   一行循环的次数
         do
           [ $j -le $i ] &&  echo  -n  "$j*$i= `echo $(($i*$j))` "
         done
         echo "  "
done
#############################################################################
for  ((i=1;i<10;i++));do
	for ((j=1;j<=i;j++));do
		echo -n "$j * $i = `let $i \* $j`"
	done
	echo ""
done

示例2:打印三角形

分析:
    使用双层循环
    外层循环控制输出行数i:9次    i=1   i<=9 i++      1    
    内层循环:
        第一个循环打印每行空格j    j=1 j<=10-i j++     
        第二个循环打印数字k        k=1 k<=i  k++     1
        i(取值)   1   2   3   ... 9
        j(个数)   9   8   7       1   j<=10-i
        k(个数)   1   2   3       9   k<=i

for ((i=1; i<10; i++))
do
   for ((j=1; j<=10-i; j++))
   do
      echo -n " ";
   done
   for ((k=1; k<=i; k++))
   do
       echo -n "$i "
   done
   echo ""
done

运行后:
         1 
        2 2 
       3 3 3 
      4 4 4 4 
     5 5 5 5 5 
    6 6 6 6 6 6 
   7 7 7 7 7 7 7 
  8 8 8 8 8 8 8 8 
 9 9 9 9 9 9 9 9 9

5.4 循环控制语句

​ 在Shell中的循环结构中,还有2个语句非常有用,即break和continue语句。前者用于立即从循环中退出;

​ 而后者则用来跳过循环体中的某些语句,继续执行下一次循环。

本节将详细介绍这2个语句的使用方法。

​ break语句的作用是立即跳出某个循环结构。break语句可以用在for、while或者until等循环语句的循环体中。

​ continue语句则比较有趣,它的作用不是退出循环体。而是跳过当前循环体中该语句后面的语句,重新从循环语句开始的位置执行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

示例:

# cat for-break.sh 
#!/bin/sh
for i in `seq 10`;do
    if [ $i -eq 4 ];then
        break
    fi
    echo $i
done
# cat for-continue.sh 
#!/bin/sh
for i in `seq 10`
do
    if [ $i -eq 4 ]
    then
        continue    
    fi
    echo $i
done
#逢3过
#1-100 n
#echo $n | grep 3   echo $?  $?=0  包含了3   跳过
#m=$((n%3))   m=0跳过      

#!/bin/bash
for i in {1..100};do
        r=$[i%3]
        echo $i|  grep '3' &>/dev/null
        s=`echo $?`
        if [[ $r -eq 0 ]] || [[ $s -eq 0 ]];then
                continue
        fi
        echo $i
done

练习:

1. 使用case实现成绩优良差的判断
2. for创建20用户
   用户前缀由用户输入
   用户初始密码由用户输入
   例如:test01,test10
3. for ping测试指网段的主机
   网段由用户输入,例如用户输入192.168.2 ,则ping 192.168.2.10 --- 192.168.2.20
   UP: /tmp/host_up.txt
   Down: /tmp/host_down.txt
4. 使用for实现批量主机root密码的修改
   成功或失败都必须记录
   提示:主机IP存放在一个文件中
   SSH:实现公钥认证,执行远程中主机命令
   实现公钥认证
   # ssh-keygen     在用于管理的主上生成密钥对
   # ssh-copy-id -i 192.168.2.3

编写一个shell脚本程序,使用shell编写一个菜单,分别实现列出以下内容:

[root@localhost day05]# vim cat.sh
cat << EOF
1:List you selected directory
2:Change to you selected directory
3:Create a new file
4:Edit you selected file
5:Remove you selected file
q/Q:Exit Menu
EOF
until false;do
    read -p "请输入你的选择[1-5]q/Q:" c
    case $c in
        1)
        ls;;
        2)
        cd;;
        3)
        touch file;;
        4)
        echo this is a > file;;
        5)
        read -p "请输入要删除的文件名:" f
        rm -rf $f && echo "$f文件已删除"
        ;;
        q|Q)
        break;;
    esac
done
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值