bash编程初体验(三)

bash编程初体验之for


  • for

  • while

  • until


概述


文将介绍以for为代表的循环语句在shell 脚本中的应用,常见的循环语句有for, while,
until,作为循环语句,顾名思义,它就是重复地做一件事,直到满足某一条件而退出;另外,还有两个循环控制语句continue与break来配合循
环语句,以实现临时中断或跳出循环的功能;以下为for, while, until的知识点提炼:

for, while, until

	进入条件		
        	for: 列表元素非空		
        	while:条件测试结果为真		
        	until:条件测试结果为假
	退出条件 
		for: 列表元素遍历完成		
		while: 条件测试结果为假		
		until: 条件测试结果为真

循环控制语句:		
    continue: 表示提前结束本轮循环,而直接进入下一轮循环的判断;		
    break: 提前跳出循环


中,for循环有两种风格,一种给个变量,让其去遍历列表;一种是类似C语言的形式,整个循环就是控制变量,当然这个形式的for循环一般都可写成
while循环;while与until形式是一样的,只是进入与退出循环的条件相左而已,它们与read语句结合可达到逐行修改某一文件的功能,其实就
是用read以输入重定向的方式读取文件的每一行,让while去遍历每一行,且满足某条件时执行相应的语句;当然until也是类似的;

for循环中列表的生成方法:

(1) 直接给出列表
(2) 整数列表:
    (a) {start..end}
    (b) $(seq[start [step]] end)
(3) 返回列表的命令    $(COMMAND)(4) 使用glob,如:*.sh
(5) 变量引用;    $@, $*
    for 变量名 in 列表;do
    循环体
done

执行机制:
依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束。

关于双小括号法的for循环

双小括号方法,即((…))格式,也可以用于算术运算
双小括号方法也可以使bash Shell实现C语言风格的变量操作,如:
    [root@centos7 ~]#i=8
    [root@centos7 ~]#((i++))
    [root@centos7 ~]#echo $i
    9
    [root@centos7 ~]#
    for循环的特殊格式:for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))do
    循环体
done
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

亦即:    for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
等价于
    (( EXP1 ))    
    while (( EXP2 )); do
            COMMANDS
            (( EXP3 ))

while循环:

while CONDITION	do 
		循环体
		循环控制变量修正表达式	
		done
	
	CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;
	条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环;
	因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正。

until循环:

until CONDITION; do
        循环体    
        done

循环控制语句:continue

用于循环体中continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
while CONDTIITON1; do
    CMD1
    ...
if CONDITION2; then
    continue
fi
CMDn
...
done

循环控制语句:break

用于循环体中break [N]:提前结束第N层循环,最内层为第1层
while CONDTIITON1; do
    CMD1
    ...
if CONDITION2; then
    break
fi
CMDn
...
done

创建无限循环:

while true; do
    循环体
    done
    
until false; do
    循环体
done

for循环练兵场

1、判断/var/log目录下所有文件的类型。

  1 #!/bin/bash
  2 #
  3 
  4 for filename in /var/log/*  
  5 do
  6         if [ -f $filename ]  
  7         then
  8                 echo "Common file."
  9         elif [ -d $filename ] 
  10         then
 11                 echo "Birectory file."
 12         elif [ -L $filename ] 
 13         then
 14                 echo "Symlic link file."
 15         elif [ -b $filename ] 
 16         then
 17                 echo "Block spelic file."
 18         elif [ -S $filename ] 
 19         then
 20                 echo "Char spelic file."
 21         else
 22                 echo "Unknow file."
 23         fi
 24 done

wKiom1e9PX6xF5mCAABiKpuqBGQ594.png

当然,如果已经编写好了判断文件类型的脚本,还可以直接调用:

#!/bin/bash
#
# 调用filetype.sh这个脚本 
for filename in /var/log/*do
       echo $filename |./filetype.sh
done

2、添加10个用户user1-user10,密码同用户名。

 1 #!/bin/bash
 2 #
 3 while [[ $1 -lt 1 ]] 
 4 do
 5         read -p "Enter a username: " user 
 6         if [ -n user ]  #判断是否为非空
 7         then 
 8                 break 2
 9         fi
 10 done
 11 
 12 for i in {1..10}
 13 do
 14         useradd ${user}${i}
 15         echo ${user}${i} |passwd --stdin ${user}${i} &> /dev/null
 16         echo "Add ${user}${i} finished."
 17 done

wKioL1e9P5qAiQp4AABxJ09hzm8826.png

3、/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K开头的文件输出为文件加stop,以S开头的文件输出为文件名加start; “K34filename stop” “S66filename start”

  1 #!/bin/bash
  2 #
  3 for i in `ls /etc/rc.d/rc3.d`  
  4 do
  5         KS_file=`echo $i |cut -c1`  
  6 
  7         case $KS_file in  
  8         K)  
  9                 echo -e "$i\tstop"
 10                 ;; 
 11         S) 
 12                 echo -e "$i\tstart"
 13                 ;; 
 14         *) 
 15                 echo "Unknow file."
 16                 ;; 
 17         esac 
 18 done

wKiom1e9P9axURVbAABCO6T2yJE151.png

4、写一个脚本,提示输入正整数n的值,计算1+2+3+…n的总和。

1 #!/bin/bash
2 #
3 read -p "Please input a integer: " int
4 declare -i sum=0
5 
6 for i in $(seq 1 $int)
7 do
8         sum=$[$sum+$i]
9 done
10 echo "sum is $sum"

wKioL1e9QBLyWfUMAAArqyr6X8Y227.png

当然,也可以这样:

  1 #!/bin/bash
  2 #
  3 read -p "Please input a integer: " int
  4 declare -i sum=0
  5 
  6 for ((i=0;i<=$int;i++))  7 do
  8         sum+=$i  
  9 done 
  10 echo "sum is $sum"

5、打印九九乘法表

 1 #!/bin/bash
 2 #
 3 
 4 for j in {1..9} 5 do
 6         for i in $(seq 1 $j) 7         do
 8                 echo -n -e "${i}X${j}=$[$i*$j]\t"
 9         done
 10         echo 
11 done

wKiom1e9QHHzvtv4AAB067Dt7o8438.png

当然,也可以这样:

1 #!/bin/bash
 2 #
 3 # for的特殊用法
 4 for ((j=1;j<=9;j++)) 5 do
 6         for ((i=1;i<=$j;i++)) 
 7         do
 8                 echo -n -e "${i}X${j}=$[$i*$j]\t"
 9         done
 10         echo 
11 done

6.写一个脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态。

 1 #!/bin/bash 
 2 #
 3 read -p "Please input a network address: " ip 
 4 
 5 Cutip=$(echo $ip |cut -d. -f1-3). # 此处可按实际网段修改,注意后面要加个.
 6 
 7 if echo $ip |grep -q -E '\<((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{
   2}|2[0-4][0-9]|25[0-5]))\>' &> /dev/null 
 8 then
 9         for ((i=105;i<110;i++))  # i可按实际需求修改,此处只测试5个ip,譬如i=100;i<=255;i++
 10         do
 11                 if  ping -c 1 -W 1 ${Cutip}${i} &> /dev/null
 12                 then
 13                         echo "${Cutip}${i} is up"
 14                 else
 15                         echo "${Cutip}${i} is down"
 16                 fi
 17         done
 18 else
 19         echo "$ip is invaild."
 20 fi

wKiom1e9QR2DA2tVAABlWL_1Ld0788.png

7.写个脚本,实现如下字样

   *
  ***
 ******
********

分析:

星号:每行的星号都是从1开始的奇数递增,如果高当前行为n,则每行的星号个数为:2n-1
空格:如果设总行数为N,则每一行中空格的个数为:N-n
  1 #!/bin/bash 
  2 #
  3 read -p  "Please input a number: " N  # 代表要打印的行数
  4 
  5 if echo $n |grep -E "[0-9]*" &> /dev/null  
  6 then  
  7         for n in `seq 1 $N`  # n代表当前行
  8         do
  9                 for ((k=(N-n);k>0;k--))   # k代表空格
 10                 do
 11                         echo -n  " "
 12                 done 
 13                 for ((s=1;s<=(2*n-1);s++)) # s代表星号
 14                 do
 15                         echo -n "*"
 16                 done 
 17                 echo 
 18         done 
 19 else
 20         echo "number is invalid."
 21 fi

wKiom1e9QajRToIfAABm9UxrFlg301.png

8.打印国际象棋棋盘

国际象棋,就是一个八行八列,两种颜色相间的一个棋盘,如下图:

wKiom1e9QcmRT5S3AAGCumVhqLM840.png

思路一:找出每个颜色块所对应的坐标,其所在行记为l,其所在列记为n,发现(l+n)%2如果为零,则为一种颜色A,如果(l+n)不为0,则为另一种颜色B;

思路二:奇数行(列)的颜色布局是相同的,偶数行(列)的颜色布局是相同的;其中,奇数行里面,奇数列对应的颜色是A,偶数列对应的颜色是B; 偶数行里面,奇数列对应的颜色是B,偶数表对应的颜色是A.

思路一代码:

  1 #!/bin/bash 
  2 #
  3 for ((l=1;l<=8;l++))   # l为行数
  4 do
  5         for ((n=1;n<=8;n++))  # n为列数
  6         do
  7                 if [ $[($l+$n)%2] -eq 0 ]  
  8                 then  
  9                         echo -ne "\e[41;1m  \e[0m"  # 打印时要加参数 -n,即不换行
 10                 else
 11                         echo -ne "\e[43;1m  \e[0m"
 12                 fi 
 13         done 
 14         echo 
 15 done

wKioL1e9ShSyGIumAAAdJN9svHU214.png

思路二代码:

1 #!/bin/bash
  2 #
  3 for ((l=1;l<=8;l++))  # l代表行
  4 do
  5         if [ $[$l%2] -eq 0 ]  
  6         then  
  7                 for ((n=1;n<=8;n++)) # n代表列
  8                 do
  9                         if [ $[$n%2] -eq 0 ] 
  10                         then 
  11                                 echo -ne "\e[45;1m  \e[0m"
 12                         else
 13                                 echo -ne "\e[46;1m  \e[0m"
 14                         fi 
 15                 done 
 16         else
 17                 for ((n=1;n<=8;n++)) 
 18                 do
 19                         if [ $[$n%2] -eq 1 ] 
 20                         then 
 21                                 echo -ne "\e[45;1m  \e[0m"
 22                         else
 23                                 echo -ne "\e[46;1m  \e[0m"
 24                         fi 
 25                 done 
 26         fi 
 27         echo 
 28 done

wKiom1e9SkDgcvLFAAAejndWLkk592.png


while 练兵场

1、求100以内所有正整数之和

 1 #!/bin/bash 
 2 #
 3 
 4 declare -i sum=0
 5 declare -i i=1
 6 
 7 while [ $i -le 100 ] 8 do
 9         let sum+=$i
 10         let i++11 done12 echo "1-100之和为 $sum"

wKiom1e9TUfiO-K7AAAqL_Ln7i8578.png

2、通过ping命令探测10.1.249.1-254范围内的所有主机的在线状态,统计在线主机和离线主机各多少

  1 #!/bin/bash 
  2 #
  3 read -p "Enter 10.1.249.0网段或ip: " ip  4 
  5 Cutip=$(echo $ip |cut -d. -f1-3)   # 注意此处的变量赋值
  6 declare -i i=100  # 此处可按实际需要修改
  7 declare -i uphosts=0
  8 declare -i downhosts=0
  9 
 10 if echo $ip |grep -q -E '\<((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9][0-9]?|1[0-9]{
    2}|2[0-4][0-9]|25[0-5]))\>'
 11 
 12 then
 13 while [ $i -le 110 ]; do # 此处可按实际需要修改 
 14         pip=$Cutip.$i  # 此变量不能定义在while循环之外
 15         ping -c 1 -W 1 $pip &> /dev/null 
 16 
 17         if [ $? -eq 0 ]; then
 18                 echo "$pip is up."
 19                 let uphosts++ 
 20         else
 21                 echo "$pip is down."
 22                 let downhosts++ 
 23         fi
 24         let i++ 25 done
 26 fi
 27 echo "The online hosts sum is $uphosts."
 28 echo "Then downline hosts sum is $downhosts."

wKioL1e9WEngV_DLAACEkwxI-IA570.png

3、打印九九乘法表

  1 #!/bin/bash 
  2 #
  3 declare -i j=1
  4 
  5 while [ $j -le 9 ]  
  6 do
  7         declare -i i=1
  8         while [ $i -le $j ]  
  9         do
 10                 echo -n -e "${i}X${j}=$[$i*$j]\t"
 11         let i++ 
 12         done 
 13         echo 
 14 let j++ 
 15 done

wKiom1e9WHKTBq_KAABaq-_XHWo112.png

当然,也可以这样:

1 #!/bin/bash
  2 #
  3 ((j=1))  
  4 while ((j<=9)); do
  5         ((i=1))  
  6         while ((i<=$j)); do
  7                 echo -en "${i}X${j}=$[$i*$j]\t"
  8                 ((i++))  
  9         done 
  10         echo 
 11         ((j++)) 
 12 done

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

 1 #!/bin/bash 
 2 #
 3 declare -i max=0
 4 declare -i min=10
 5 ((i=1)) 
 6 while ((i<=10)); do
 7         random=$[$RANDOM%10+1] 
 8         ((i++)) 
 9         echo $random
 10         [ $min -gt $random ] && min=$random
 11         [ $max -lt $random ] && max=$random
 12 done
 13 
 14 echo "MAX is $max"
 15 echo "MIN is $min"

wKiom1e9WKTz3ki4AAA4QAQ3zI8772.png

5、打印国际象棋棋盘

 1 #!/bin/bash 
 2 #
 3 declare -i n  # n代表行
 4 declare -i l  # l代表列
 5 
 6 ((n=1)) 
 7 while ((n<=8)); do
 8         ((l=1)) 
 9         while ((l<=8)); do
 10                 if [ $[($n+$l)%2] -eq 0 ]; then
 11                         echo -en "\e[44;1m  \e[0m"
 12                 else
 13                         echo -en "\e[47;1m  \e[0m"
 14                 fi
 15                 ((l++))
 16         done
 17         echo 
18         ((n++))
19 done

wKioL1e9WPTBuPbhAAAeiUXaCiA117.png

 1 #!/bin/bash
 2 #
 3 declare -i n    # n代表行
 4 declare -i i    # i代表列
 5 
 6 n=1
 7 while ((n<=8)); do
 8         if [ $[$n%2] -eq 0 ]; then 
 9                 i=1
 10                 while ((i<=8)); do
 11                         if [ $[$i%2] -eq 0 ]; then
 12                                 echo -en "\e[47;1m  \e[0m"
 13                         else
 14                                 echo -en "\e[46;1m  \e[0m"
 15                         fi
 16                         ((i++))
 17                 done
 18         else
 19                 i=1
 20                 while ((i<=8)); do
 21                         if [ $[$i%2] -eq 1 ]; then
 22                                 echo -en "\e[47;1m  \e[0m"
 23                         else
 24                                 echo -en "\e[46;1m  \e[0m"
 25                         fi
 26                         ((i++))
 27                 done
 28         fi
 29         ((n++))
 30 echo
 31 done

wKioL1e9WZbSdlTLAAAqD7LawhQ519.png


until练兵场

1、打印九九乘法表

1 #!/bin/bash
 2 #
 3 declare -i j=1
 4 
 5 until [ $j -gt 9 ] 6 do
 7         i=1
 8         until [ $i -gt $j ] 
 9         do
 10                 echo -n -e "${i}X${j}=$[$i*$j]\t"
 11         let i++
 12         done
 13         echo
 14 let j++
 15 done

wKiom1e9WeGCGUFIAABbCwqXlW8594.png

2、求1-100之和

1 #!/bin/bash
2 #
3 
4 declare -i sum=0
5 declare -i i=100
6 
7 until [ $i -lt 1 ]
8 do
9         let sum+=$i
10         let i--
11 done
12 echo "sum is $sum"

wKiom1e9Wmai74zdAAAcXJNXQb0277.png

3、随机生成10以内的数字,实现猜字游戏,提示比较大或小,相等则退出。

 1 #!/bin/bash
 2 #
 3 read -p "Please input 1-10之间的整数:" num 
 4 random=$[$RANDOM%10+1] 
 5 
 6 if echo $num |grep -q -E '\<([1-9]|[0]?)\>'; then
 7         until [ $num -eq $random ]; do
 8                  [ $num -gt $random ] &&  echo "This num is too big,please give a dot." 
 9                  [ $num -lt $random ] &&  echo "This num is too dot,please give a big." 
 10                  read -p "Please input 1-10之间的整数:" num
 11         done
 12 
 13         echo "Congratulations, you guessed right."
 14 else
 15         echo "num is invalid."
 16 fi

wKiom1e9WzbQDPjVAABekKxRZ80547.png

本文其它案例会持续更新……

止战

2016.8.24

原创文章,作者:Liansir,如若转载,请注明出处:http://www.178linux.com/39741

(0)
LiansirLiansir
上一篇 2016-08-24
下一篇 2016-08-24

相关推荐

  • 磁盘管理

    1、创建一个10G分区,并格式为ext4文件系统。 (1)虚拟机添加21G硬盘 Disk /dev/sdb: 21.5 GB, 21474836480 bytes, 41943040 sectors Units = sectors of 1&nbsp…

    Linux干货 2016-12-18
  • 通过堡垒机代理SSH运行Ansible(译)

    有一种常见的网络安全模式是阻止私有网络外部对应用服务器的所有连接(指除了业务数据外其它的连接,如后台管理系统和内部业务系统。译者注),然后使用 DMZ 区域中的 堡垒机 来选择性的将到服务器的流量加入白名单。 我们有这样的一个服务器池,只允许来自特定 IP 地址的 SSH 流量。这些服务器还由 Ansible…

    Linux干货 2015-02-14
  • 网络管理之虚拟网卡实现一个网卡多个地址

    一.概述 在虚拟机中实现一个网卡多个地址 完成这个功能之前需要先关闭NetworkManager功能(在centos 6系统)         chkconfig NetworkManager off   而且我们要实现虚拟网卡一个网卡多个地址只是对虚拟机有用 网卡别名…

    Linux干货 2016-09-16
  • 01Linux的发展历史

    1、1965年时,贝尔实验室(Bell Labs)加入一项由通用电气(General Electric)和麻省理工学院(MIT)合作的项目;该项目要建立一套多使用者、多任务、多层次(multi-user、multi-task、multi-level)的MULTICS操作系统。但是由于整个目标过于庞大,糅合了太多的特性,Multics虽然发布了一些产品,但是性…

    Linux干货 2016-10-14
  • shell编程之数组及环境变量

    数组 变量:存储单个元素的内存空间 数组:存储多个元素的连续的内存空间,相当于多个变量的 集合 索引:编号从0 声明数组: declare -a ARRAY_NAME declare -A ARRAY_NAME:关联数组 1.declare  -a menu  menu[0]=beef  menu[1]=chicken menu…

    Linux干货 2016-08-29
  • rpm和yum的使用,程序包编译安装以及编译apache过程中出现的问题

    一、rpm包管理          用法: rpm [选项…]              查询/验证软件包选项:   &nbsp…

    Linux干货 2016-03-19