shell编程之循环

       当需要重复运行特定的指令以满足系统管理工作需要时,条件判断语句if、case并不能很好地提供支撑,shell提供了for、while、until循环语句来满足此需求。

一、for循环语句

       for循环用于重复整个对象列表,依次遍历对列表中的独立对象,直到遍历列表完成,循环次数取决于列表中的对象数,每次循环都会执行指定的某个或某几个命令。

需要特别指出的是,循环应该指定退出条件,否则循环将不会退出,一直执行。     

       1、for循环的语法格式:

       (1)、格式1

       for var in list;do

              Command1…

       done

       也可以这样写

       for var in list

do

       Command1…

done

 

       (2)、格式2

       格式二类似于C语言中的for循环

       for  ((变量初始值;循环退出条件;变量运算))

       do

              Command1…

       done

2、列表生成方式:

       (1)、直接给出列表,如for num in 1 2 3 4 5…;do….done

       (2)、使用文件通配名机制生成文件列表,如 for file in /var/*.sh

       (3)、使用{}或seq命令

                     for i in {1..10};do echo $i ;done;

                     for i in `seq 1 10`; do echo $i ;done;

              seq用法说明:

                     seq [start] [step] end

                          起始数字 步长 结束数字

例: seq 1 3 10

blob.png

       (4)、使用命令生成,如for file in `ls –A /etc/`;do echo $file;done;

       (5)、脚本参数引用$*、$@,注意两者之间的区别,$*将所有参数当作一个字符串,$@将每个参数当作独立的字符串。

 

例1:用for循环计算100以内正整数的奇数和&偶数和

#!/bin/bash
#
sum=0
for i in `seq 1 2 100`;do
sum=$[$sum+$i]
done
echo $sum

blob.png

第2种方式:

#!/bin/bash
#
sum=0
for ((num=1;num<=100;num+=2))
do
sum=$[$sum+$num]
done
echo $sum

blob.png

偶数的求和方式与奇数的相差无几,这里不再重复。

 

例2、判断/var/目录下的文件类型

#!/bin/bash
#
dir=/var/
varfile=`ls -A $dir`
for file in $varfile;do
echo "The type of $dir$file is :`file -b $dir$file` "
done

blob.png

       for语句可与条件判断结合,完成复杂任务。

例3、给脚本传递两个正整数,第二个整数大于第一个整数,计算两个整数之间所有整数的和。

#!/bin/bash
#
sum=0
if [ $# -lt 2 ];then
echo "Two int number needed"
exit 222
elif [ $1 -gt 0 ] &> /dev/null && [ $2 -gt 0 ]  &>/dev/null && [ $2 -gt $1 ] &> /dev/null;then
for  ((i=$1;i<=$2;i++));do
sum=$[$sum+$i]
done
echo $sum
else
echo "Please enter two int number,and the second arg must bigger than the first arg"
exit 22
fi

blob.png

 

二、while语句

       while语句在循环前对运行条件进行判断,测试条件满足时,循环将一直被执行,直到测试条件失败,退出循环。

       1、while语法格式      

while Condition; do

循环体

done

Condition:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环

因此:Condition一般应该有循环控制变量;而此变量的值会在循环体不断地被修正

 

例1、计算100以内所有正整数之和

#!/bin/bash
#
num=1
sum=0
while [ $num -le 100 ];do
sum=$[$num+$sum]
num=$[$num+1]
done
echo $sum

blob.png

例2、利用变量RANDOM 生成10 个随机数字,输出这个10 数字,并显示其中的最大者和最小者

#!/bin/bash
#
num=1
sum=0
min=65535
while [ $num -le 10 ];do
mingbo=`echo $RANDOM`
echo $mingbo
if [ $mingbo -gt $sum ];then
sum=$mingbo
else
sum=$sum
fi
if [ $mingbo -lt $min ];then
min=$mingbo
else
min=$min
fi
let num=$num+1
done
echo  "The max number is $sum"
echo  "The min number is $min"

blob.png

例3、打印国际象棋棋盘。

blob.png

国际象棋棋盘长8列、宽8行,共计64个格子,格子间色显示。

通过观察发现:行数+列数之和对2取模为0的显示为黑色;行数+列数之和对2取模为1的显示为白色。

脚本如下:

#!/bin/bash
#
declare -i num=1
while [ $num -le 8 ];
do
for  ((j=1;j<=8;j++))
do
[ $[$[$num+$j]%2] -eq 0 ] && echo -ne "\033[40m  \033[0m" || echo -ne "\033[41m  \033[0m"
done
((num++))
echo

done

blob.png

 

      

2、while的特殊用法:用于遍历文件中的每一行

       while read line;

do

循环体

done < /Path/From/Some_file

例4、找出/etc/passwd文件中uid号为偶数,uid=gid的用户

#!/bin/bash
#

while read line;do
userid=`echo $line | cut -d : -f3`
gid=`echo $line | cut -d : -f4`
if [[ $userid%2 -eq 0 && $gid%2 -eq 0 && $userid -eq $gid ]];then
uname=`echo $line | cut -d : -f1`
echo -e "The user whose id number is even is \033[32m$uname\033[0m,
        \n and his userid is \033[32m$userid\033[0m,
        \n his group id is \033[32m$gid\033[0m"
fi
done < /etc/passwd

blob.png

 

 

三、until语句

语法格式:

until Condition; do

循环体

done

       其用法与while语句基本类似。区别在于进入条件和退出条件不同。进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“false”,则执行一次循环;直到条件测试状态为“true”终止循环。

如:计算100以内的正整数之和,用until实现。

#!/bin/bash
#
num=1
sum=0
until [ $num -gt 100 ];do
sum=$[$sum+$num]
((num++))
done

echo $sum

blob.png

四、循环控制语句

       continue、break、shift

4.1 continue:用于退出当次循环,continue后面的循环体不再运行,而是直接进入下一次循环。

语法格式:

while CONDTIITON1; do

CMD1

if CONDITION2; then

continue

fi

CMDn

done

4.2 break:用于退出循环体,不再执行循环。

       while CONDTIITON1; do

CMD1

if CONDITION2; then

break

fi

CMDn

done

例1:要求用户输入一个用户名,如输入quit则退出脚本,若输入的用户名不存在则要求用户重新输入,输入正确之后,显示该用户的uid。

#!/bin/bash
#
while true;do
read -p "Enter a user name : " uname
if [[ $uname == "quit" ]];then
break
elif [[ -z $uname ]] || ! id $uname &>/dev/null;then
echo "Wrong username,try again..."
continue
else
uid=`id -u $uname`
echo "$uname's userid is $uid"
fi

done

blob.png

4.3 shift:用于将脚本的位置参数左移一位或指定的位数。也就是执行shift之后,$2将变成$1.

 

例:给脚本传递3个参数,脚本使用格式:

script_name.sh [-D|–description "script description"] [-A|–author "script author"] /path/to/somefile;其中-D和-A可选。使用shift,分别保存传递的description、author、filename参数,并输出。

#!/bin/bash
#
if [ $# -lt 2 ];then
echo "Wrong option..."
echo "Usage : `basename $0` [-D|--description "script description"] [-A|--author "script author"] -f /path/to/somefile"
exit
fi

while [ $# -ge 2 ];do
case $1 in
-D|--description)
desc=$2
shift 2
;;
-A|--author)
author=$2
shift 2
;;
-f)
filename=$2
shift 2
;;
*)
echo "Wrong option..."
echo "Usage : `basename $0` [-D|--description "script description"] [-A|--author "script author"] -f /path/to/somefile"
exit
;;
esac
done
echo "filename is $filename;author is $author;file description is $desc"

blob.png

五、实战演练 

1、用until循环实现国际象棋棋盘

#!/bin/bash
#
declare -i x=1

until [ $x -gt 8 ]
do
for  ((y=1;y<=8;y++))
do
[ $[$[$x+$y]%2] -eq 0 ] && echo -ne "\033[40m  \033[0m" || echo -ne "\033[41m  \033[0m"
[[ $y -eq 8 ]] && echo 
done
((x++))
done

blob.png

2、用*号输出正三角,如:

blob.png

分析:第1行的空白数为:总行数-当前行数;假设总行数为5,则第1行的空白数为5-1=4

    第1行的*号数为:2*当前行数-1;第1行的*数为:2*1-1=1

    

   第2行的空白数为:总行数-当前行数;假设总行数为5,则第2行的空白数为5-2=3

    第2行的*号数为:2*当前行数-1;第1行的*数为:2*2-1=3

    

   第n行的空白数为:总行数-当前行数;假设总行数为m,则第n行的空白数为m-n

    第n行的*号数为:2*n-1;第n行的*数为:2*n-1

#!/bin/bash
#
lines=5

for i in `seq $lines`
do
for j in `seq $[$lines-$i]`
do
echo -n " "
done
for x in `seq $[$[$i*2]-1]`
do
echo -n "*"
done
echo
done

blob.png


 

 

 

原创文章,作者:M20-1钟明波,如若转载,请注明出处:http://www.178linux.com/37118

(0)
M20-1钟明波M20-1钟明波
上一篇 2016-08-18
下一篇 2016-08-18

相关推荐

  • 马哥教育网络19期+第十七周课程练习

    1、结合图形描述LVS的工作原理;     LVS (Linux Virtual Server)是一种集群(Cluster)技术,采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结…

    Linux干货 2016-09-05
  • Linux网络属性配置,计算机基础

    Linux网络属性配置,计算机基础 Linux网络属性配置(1): 计算机网络通信:TCP/IP 通过流式化数据相互通信,通过双方一致的时钟频率来完成信号传输; 有两种方式传输:同步传输,异步传输; 借助于介质传输:同轴电缆、网线、无线等; 要想相互通信,也要必须遵循一种(复杂)组织机制,就产生了协议; 通过把协议分层,来分别解决传输过程中各种复杂的操作; …

    Linux干货 2016-09-05
  • shell脚本初步

    shell脚本编程初步 程序:由数据和指令组成, 指令:由程序文件提供 数据:可以通过IO设备、文件、管道来得到, 程序:算法+数据结构 变量:变量名+变量名指向的内存空间 变量赋值: name = value变量类型:存储格式:字符 数值(精确数值 近似数值)   表示数据范围  &nb…

    Linux干货 2016-08-15
  • rpm包管理

    linux程序包管理 RPM ================================================================== #ldd 查看二进制程序调用的动态链接库 #ldconfig  -p  显示本机已缓存的所有可用库文件     dll: Dynamic…

    Linux干货 2016-08-18
  • Nginx

    Nginx简介     Nginx(”engine x”)是俄罗斯人Igor Sysoev(伊戈尔.塞索耶夫)编写的一款高性能的HTTP和反向代理服务器。Nginx能够选择高效的epoll、Kqueue、eventport作为网络I/O模型,在高连接并发的情况下,Nginx是Apache服务器不错的替代品,它能够支持高…

    2017-05-07
  • find总结及练习

    文件查找: 在文件系统上查找符合条件的文件; 文件查找:locate, find非实时查找(数据库查找):locate 实时查找:find locate: 依赖于事先构建的索引;索引的构建是在系统较为空闲时自动进行(周期性任务);手动更新数据库(updatedb); 索引构建过程需要遍历整个根文件系统,极消耗资源; 工作特点: 查找速度快; 模糊查…

    Linux干货 2016-07-22