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

相关推荐

  • 谷歌三大核心技术(三)Google BigTable中文版

    摘要 Bigtable是一个分布式的结构化数据存储系统,它被设计用来处理海量数据:通常是分布在数千台普通服务器上的PB级的数据。Google的很多项目使用Bigtable存储数据,包括Web索引、Google Earth、Google Finance。这些应用对Bigtable提出的要求差异非常大,无论是在数据量上(从URL到网页到卫星图像)还是在响应速度上…

    Linux干货 2015-04-13
  • bash功能特性六 bash操作环境

    一、bash查找命令的顺序     1、以相对路径或绝对路径执行的命令;     2、由alias找到该命令来执行;     3、由bash内置的命令来执行;     4、通过$PATH这个变量的顺序找到的第一个命令来执…

    Linux干货 2015-04-22
  • 细说CP使用

    cp详细用法和常用选项

    Linux干货 2017-11-26
  • 配置LAMP (php-fpm模式)部署步骤

    配置LAMP (php-fpm模式)部署步骤 1.安装mariadb yum install maridb-server -y 1).配置server.cnf cp /etc/my.cnf.d/server.cnf{,.back} vim /etc/my.cnf.d/server.cnf ##mariadb服务器端配置文件 [mysqld] ##以下项是优化…

    Linux干货 2017-06-02
  • LVM应用

    1、创建一个2G的文件系统,块大小为2048byte,预留1%可用空间,文件系统ext4,卷标为TEST,要求此分区开机后自动挂载至/test目录,且默认有acl挂载选项 ·首先在虚拟机当中添加指定大小的硬盘,添加完成后,系统不会自动扫描添加的硬盘设备,键入命令重新扫描SCSI总线来添加设备   echo "- – -&quo…

    Linux干货 2016-08-30
  • 磁盘管理

    硬盘物理结构      扇区  磁头  磁道   柱面   磁道数      扇区*一个磁道上的扇区个数*磁头数=柱面      柱面*磁道数=硬盘大小      一个扇区512字节   &…

    Linux干货 2017-08-26