RHCE的学习(23)

第五章 流程控制之循环

for循环

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

带列表的for循环

  • 格式:

格式1:
for variable in {list}
do
    statement1
    statement2
    ...
done


格式2:
for variable in {list};do
   statement1
   statement2
   ...
done
  • 分析

    • variable称为循环变量

    • list是一个列表,可以是一系列的数字或者字符串,元素之间使用空格隔开

    • do和done之间的所有的语句称为循环体,即循环结构中重复执行的语句

    • 执行时,Shell会将in关键字后面的list列表的第1个元素的值赋给变量variable,然后执行循环体,当循环体中的语句执行完毕之后剩余以此类推,当list列表中的所有的元素都被访问后,for循环结构终止,程序将继续执行done语句后面的其他的语句

  • 例1:

方法1:直接列出元素方法
[root@server ~]# vim  for1.sh
#!/bin/bash
​
for ip in 192.168.48.130 192.168.48.131
do
        echo $ip
done
​
[root@server ~]# bash for1.sh 
192.168.48.130
192.168.48.131
方法2:使用大括号
[root@server ~]# vim  for2.sh
#!/bin/bash
​
for ip in 192.168.48.{130..140..2} # 使用{start..end..step} 进行扩展
do
        echo  $ip
done
[root@server ~]# bash for2.sh 
192.168.48.130
192.168.48.132
192.168.48.134
192.168.48.136
192.168.48.138
192.168.48.140
方法3:使用seq  
# 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

seq相关用法:

https://blog.youkuaiyun.com/qq_37120573/article/details/82556177

  • 例2:获取指定目录下的所有目录的文件名

[root@server ~]# vim for3.sh
#!/bin/bash
​
for  FILE  in  $(ls -F / | grep /$)
do
        echo  $FILE
done
​
[root@server ~]# bash for3.sh 
afs/
boot/
dev/
etc/
home/
media/
mnt/
opt/
proc/
root/
run/
srv/
sys/
tmp/
usr/
var/
# ls -F  :用于将目录内的文件按照文件类型进行归类显示,会在不同类别的文件名尾部增加不同的
#标识符,目录以/结尾、链接文件以@结尾、可执行文件以*结尾、普通文件无符号
# grep /$ :表示以/结尾的行
  • shell允许用户指定for语句的步长,格式如下

for variable in {start..end..step}
do
    statement1
    statement2
    ...
done
  • 例3:计算1+2+3+4+5+……+100和

[root@server ~]# bash for4.sh
#!/bin/bash
​
sum=0
for i in {1..100..1}
do
        ((sum=sum+i))
done
echo "sum=$sum"
# 上例修改
[root@server ~]# bash for4.sh
#!/bin/bash
​
sum=0
for i in $(seq 100)
do
        ((sum=sum+i))
done
echo "sum=$sum"

不带列表的for循环

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

  • 原则:for不提供循环列表,shell将从命令行获取循环列表数据及条件,格式:

for variable
do
    statement1
    statement2
    ...
done
  • 由于系统变量$@可以获取所有位置参数,以上的语法等价于:

for variable in $@或$*
do
    statement1
    statement2
    ...
done
  • 例4:

[root@server ~]# vim for5.sh
#!/bin/bash
​
for  arg
do      
        echo  $arg
done    
[root@server ~]# bash for5.sh   {1..10}

基于C语言风格的for循环

  • 格式

for ((初始化;条件表达式;步长))    # 注意:2个园括号
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

  • 例5:面试题,批量创建账户

要求:

  • 用户名以test开头,按数字序号变化;
  • 一共添加30个账号,即test01,tes02...,test30
  • 用户初始密码为123456
分析: 
    根据要求使用循环语句完成
    创建用户使用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}
  • 注意:i++表示置后自增,++i置前自增

[root@server ~]# x=1
[root@server ~]# y=2
[root@server ~]# echo  $((x++))
1
[root@server ~]# echo $x
2
[root@server ~]# echo  $((++y))
3
[root@server ~]# echo $y
3
  • 例6:编写一个 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

while循环

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

格式

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

while循环读取文件

# 法1 ,采用exec读取文件
[root@server ~]# vim  file1.txt
data1
data2
data3
data4
data5
​
​
[root@server ~]# vim  while1.sh
​
#!/bin/bash
​
exec  < file1.txt
while  read   a
do
        echo $a
done
​
# exec  < file1.txt  将file.txt文件内容读入到标准输入中
# read   a  表示从标准输入中按照行读取内容到变量a
# 法2:使用cat读取文件,通过管道符进入while循环处理
​
cat  文件名  |  while  read line
do  
    statement1
    statement1
    ……
done
#法3 : 在while循环尾部使用输入重定向指定输入数据
while  read  line
do
    statement1
    statement1
    ……
done  <  文件名
变量参数是按换行符分割

示例

  • 例1:猜商品价格,通过变量RANDOM获取随机整数并控制20以内,提示用户猜测商品价格,猜测时需要记录次数,猜中后退出程序

分析:
    产生随机数
    猜中退出循环,显然要用死循环(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 ))
  • 例2:工作过程中遇到要从一个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))

until循环

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

作用

  • until循环不断地重复执行循环中的语句,直至某个条件成立,与while循环的执行条件相反

until  expreession
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

select循环

概念

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

  • select语句的基本语法如下:

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

示例

  • 例1:选择mysql版本

[root@server ~]# vim select1.sh 
#!/bin/bash
​
select mysql_version in 5.1 5.6
do
    echo $mysql_version
done
​
[root@server ~]# bash select.sh 
1) 5.1
2) 5.6
#? 1
5.1
#? 2
5.6
#? 3
  • 例2:选择水果

[root@server ~]# vim select2.sh 
​
#!/bin/bash
PS3='Choose your favorite fruit: '
​
#设置提示符字符串
echo $PS3
select fruit in "Apples" "Bananas" "Pears" "Watermelons" "Grapes"
do
    echo
    echo "Your favorite fruit is $fruit."
    break
done
​
exit 0
​
[root@server ~]# bash select2.sh 
 
1) Apples
2) Bananas
3) Pears
4) Watermelons
5) Grapes
Choose your favorite fruit: 1
 
Your favorite fruit is Apples.

循环嵌套

在程序设计语言中,嵌套的循环也是一种非常常见的结构。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 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

循环控制

组成

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

  • continue: 作用不是退出循环体。而是跳过当前循环体中该语句后面的语句,重新从循环语句开始的位置执行

详细语法:

示例

  • 例1:判断素数

[root@server ~]# vim  for7.sh
#!/bin/bash

read  -p  "请输入一个正整数: "  prime

if ((prime<2))
then
        echo  "数据错误,请输入大于等于2的正整数."
else
        for ((i=2;i<prime;i++))
        do
                if ((prime%i==0))
                then
                        echo  "平数"
                        break
                fi
        done
        if ((prime==i))
        then
                echo "素数"
        fi
fi
  • 例2:计算100到150之间不能被3整除的数,输出时一行显示5个

#!/bin/bash

count=0
for ((i=100;i<=150;i++))
do
        if ((i%3==0))
        then
                continue
        fi
        echo -ne "$i\t"
        ((count++))
        if ((count%5==0))
        then
                echo
        fi
done

echo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值