上篇我们学习了shell中条件选择语句的用法。接下来本篇就来学习循环语句。在shell中,循环是通过for, while, until命令来实现的。下面就分别来看看吧。

for

for循环有两种形式:

for-in语句

基本格式如下:

  1. for var in list
  2. do
  3. commands
  4. done

list代表要循环的值,在每次循环的时候,会把当前的值赋值给var(变量名而已,随意定), 这样在循环体中就可以直接通过$var获取当前值了。

先来一个例子吧:

  1. #!/bin/bash
  2. for str in a b c d e
  3. do
  4. echo $str
  5. done

以上会根据空格将abcde分割,然后依次输出出来。

如果以上例子不是以空格分割,而是以逗号(,)分割呢?

  1. #!/bin/bash
  2. list="a,b,c,d,e"
  3. for str in $list
  4. do
  5. echo $str
  6. done

结果输出a,b,c,d,e

  造成这个结果的原因是:for...in循环默认是循环一组通过空格或制表符(tab键)或换行符(Enter键)分割的值。这个其实是由内部字段分隔符配置的,它是由系统环境变量IFS定义的。当然,既然是由环境变量定义的,那当然也就能修改啊。

另一个根据用户名杀死进程(强制退出用户)的例子:

  首先输入用户命,如果用户未root提示不能杀死root,否则杀死相关进程

  1. #!/bin/bash
  2. #input username and kill relactive process for kill user
  3. echo "please input username for kill"
  4. read username
  5. #if username is root ,exit
  6. if [ ${username} = 'root' ]
  7. then
  8. echo "root can not kill"
  9. exit
  10. fi
  11. #get user PID
  12. PID=`/usr/bin/ps -aux | /usr/bin/grep qlq | /usr/bin/awk '$1="qlq" {print $2}'`
  13. for killpid in $PID
  14. do
  15. kill - $killpid
  16. done
  17. echo "killed ok!"

另外 一个利用for in 实现ls的功能:

  1. #!/bin/bash
  2. #for xx in xxx usage
  3. for pd in $(/usr/bin/ls /root/sshDemo/)
  4. do
  5. echo $pd
  6. done

  上面$(/usr/bin/ls /root/sshDemo/)本身返回的就是一行一行的数据,所以可以用做集合

结果:

  1. [root@VM_0_12_centos sshDemo]# ./testFor.sh
  2. addUserBatch.sh
  3. delUserBatch.sh
  4. killUser.sh
  5. testApache.sh
  6. testFile.sh
  7. testFor.sh
  8. testKuohao.sh
  9. testNum.sh
  10. testSelect.sh
  11. testShift.sh

修改IFS值

  1. #!/bin/bash
  2. #定义一个变量oldIFS保存未修改前的IFS的值
  3. oldIFS=$IFS
  4. #修改IFS值,以逗号为分隔符
  5. IFS=$','
  6. list=a,b,c,d,e
  7. list2="a b c d e"
  8. for var in $list
  9. do
  10. echo $var
  11. done
  12. for var2 in $list2
  13. do
  14. echo $var2
  15. done
  16. #还原IFS的值
  17. IFS=$oldIFS

以上第一个循环会分别输出abcde几个值。而第二个循环会输出a b c d e(即未处理)。因为我们把IFS的值设置为逗号了, 当然,不一定要是逗号,想设置什么,你说了算!

C语言风格的for循环

bash中c语言风格的for循环遵循如下格式:

for (( variable assignment ; condition ; iteration process ))

一个例子足以说明:

  1. #!/bin/bash
  2. for (( i = ; i <= ; i++ ))
  3. do
  4. echo $i
  5. done

上面例子循环11次,从0到10依次输出。稍微有过编程基础的都对此应该很熟悉。就不做详细阐述了。

例如:此种风格的for循环批量添加用户的脚本:

  1. #!/bin/bash
  2. #adduser batch
  3. echo "please input username:"
  4. read username
  5. echo "please input number to create:"
  6. read number
  7. #start to create user
  8. for(( i=;i<="${number}";i++ ))
  9. do
  10. /usr/sbin/adduser "${username}${i}" > /dev/null > /dev/null
  11. done
  12. #add finished
  13. echo "add OK!"
  14. echo "please input passwd for users"
  15. read password
  16. for(( i=;i<="${number}";i++ ))
  17. do
  18. /usr/sbin/usermod -p "${password}" "${username}${i}" > /dev/null > /de
  19. v/null
  20. done

结果:

  1. [root@VM_0_12_centos sshDemo]# ./addUserBatch.sh
  2. please input username:
  3. ppp
  4. please input number to create:
  5.  
  6. add OK!
  7. please input passwd for users
  8.  
  9. [root@VM_0_12_centos sshDemo]# tail - /etc/passwd
  10. ppp16:x::::/home/ppp16:/bin/bash
  11. ppp17:x::::/home/ppp17:/bin/bash
  12. ppp18:x::::/home/ppp18:/bin/bash
  13. ppp19:x::::/home/ppp19:/bin/bash
  14. ppp20:x::::/home/ppp20:/bin/bash
  15. [root@VM_0_12_centos sshDemo]# tail - /etc/shadow
  16. ppp16::::::::
  17. ppp17::::::::
  18. ppp18::::::::
  19. ppp19::::::::
  20. ppp20::::::::

例如:批量删除用户的脚本:

  解释:去passwd查找第一列过滤输入的关键词,然后在第一列中查找关键词,如果查到就输出给users,最后循环删除:$?用于判断上一次命令的返回状态码,如果返回0代表正常结束,否则就是失败!

  1. #!/bin/bash
  2. #delete user batch
  3. echo "please input username word to delete"
  4. read word
  5. #get All users like word*
  6. users=`/usr/bin/grep ${word} /etc/passwd | awk -F: -v word1=${word} 'index($1,wo
  7. rd1)> {print $}'`
  8. if [ "${users}" = '' ]
  9. then
  10. echo "user is does not exist!"
  11. exit
  12. fi
  13. for username in ${users}
  14. do
  15. /usr/sbin/userdel -rf ${username} > /dev/null >/dev/null
  16. done
  17. if [ "" = "$?" ]
  18. then
  19. echo "delete ok!"
  20. else
  21. echo "delete failed!"
  22. fi

while循环

  如果你习惯了其它语言的while循环,那么到这儿你又会发现这个while循环有点变态了。与其它编程语言while的不同在于:在bash中的while语句,看起来似乎是结合了if-then语句(参考上一篇)和for循环语句。其基本格式如下:

  1. while test command
  2. do
  3. other commands
  4. done
  1.  

与if-then语句一样,后面接test命令,如果test后面的命令的退出状态码为0. 那么就进入循环,执行do后面的逻辑。要注意在do后面的逻辑中写条件,避免死循环。

既然是接test命令,那么一切都可以参考if-then的test

示例一:

  1. #!/bin/bash
  2. flag=
  3. while test $flag -le
  4. do
  5. echo $flag
  6. # 如果没有这句,那么flag的值一直为0,就会无限循环执行
  7. flag=$[$flag + ]
  8. done

以上判断flag是否大于或者等于10, 如果满足条件,那么输出当前flag的值,然后再将flag的值加1。最终输出的结果为0到10的结果。

结合上一篇文章test的写法,我们还可以将以上示例变形为如下:

示例二:

  1. #!/bin/bash
  2. flag=
  3. while [ $flag -le ]
  4. do
  5. echo $flag
  6. flag=$[$flag + ]
  7. done
  1.  

示例三:

  1. flag=
  2. while (( $flag <= ))
  3. do
  4. echo $flag
  5. flag=$[$flag + ]
  6. done
  1.  
  • shift指令:  参数左移,每执行一次,参数序列顺次左移一个位置,$#的值减一。用于分别处理每个参数,移出去的参数不再可用。
    例如:shift+while循环实现求和:
  1. #!/bin/bash
  2. #shift useage
  3. if [ $# -eq ]
  4. then
  5. echo "please input the parameters"
  6. exit
  7. fi
  8. sum=
  9. while [ $# -gt ]
  10. do
  11. sum=$(($sum+$))
  12. shift
  13. done
  14. echo "$sum"

结果:

  1. [root@VM_0_12_centos sshDemo]# sh -x testShift.sh
  2. + '[' -eq ']'
  3. + sum=
  4. + '[' -gt ']'
  5. + sum=
  6. + shift
  7. + '[' -gt ']'
  8. + sum=
  9. + shift
  10. + '[' -gt ']'
  11. + sum=
  12. + shift
  13. + '[' -gt ']'
  14. + sum=
  15. + shift
  16. + '[' -gt ']'
  17. + echo

计算过程:

  1.  

总结:对于比较大小的左右都要有空格,例如:[ $# -eq 0 ]

  对于计算值的左右都不能有空格,例如:sum=$(($sum+$1))

until循环语句

until语句基本格式如下:

  1. until test commands
  2. do
  3. other commands
  4. done
  1.  

在掌握while循环语句之后, until语句就很简单了。until语句就是与while语句恰好相反, while语句是在test命令退出状态码为0的时候执行循环, 而until语句是在test命令退出状态码不为0的时候执行。

示例:

  1. #!/bin/bash
  2. flag=
  3. until (( $flag > ))
  4. do
  5. echo $flag
  6. flag=$[ $flag + ]
  7. done

以上输出0到10的值。until后面的条件与上面while例子完全相反。

  好啦,到此,我们学完了shell的循环语句啦。不过上面我们写的循环语句都是根据条件执行完毕,如果我们在执行的过程中想退出,该怎么办?接下来就继续看看怎么控制循环语句。

控制循环

与其它编程语言一样,shell是通过break和continue命令来控制循环的。下面就分别来看看二者的基本用法:

break

  1. break用于跳出当前循环

示例一:

  1. #!/bin/bash
  2. for (( flag=; flag <= ; flag++ ))
  3. do
  4. if (( $flag == ))
  5. then
  6. break
  7. fi
  8. echo $flag
  9. done
  1.  

以上当flag的值为5的时候,退出循环。输出结果为0-4的值。

  1. break用于跳出内层循环

示例二:

  1. #!/bin/bash
  2. flag=
  3. while (( $flag < ))
  4. do
  5. for (( innerFlag=; innerFlag < ; innerFlag++ ))
  6. do
  7. if (( $innerFlag == ))
  8. then
  9. break
  10. fi
  11. echo "innerFlag=$innerFlag"
  12. done
  13. echo "outerFlag=$flag"
  14. done
  1.  

以上代码在执行内部循环for的时候,当innerFlag值为2的时候就会跳出到外层的while循环, 由于外层循环一直flag都为0, 所以while会成为一个死循环,不停的输出:

...

innerFlag=0

innerFlag=1

outerFlag=0

...

  1. break用于跳出外层循环

break 可后接数字,用于表示退出当前循环的外层的第几层循环。

示例三:

  1. #!/bin/bash
  2. flag=
  3. while (( $flag < ))
  4. do
  5. for (( innerFlag=; innerFlag < ; innerFlag++ ))
  6. do
  7. if (( $innerFlag == ))
  8. then
  9. # 2表示外面一层循环
  10. break
  11. fi
  12. echo "innerFlag=$innerFlag"
  13. done
  14. echo "outerFlag=$flag"
  15. done
  1.  

与上面例子相比,本例就只是在break后面跟了个数字2,表示退出外面的第一层循环。最终输出:

innerFlag=0

innerFlag=1

continue

continue表示终止当前的一次循环,进入下一次循环,注意,continue后面的语句不会执行。

continue的语法与break一样,因此,就只做一个示例演示啦。

示例:

  1. flag=
  2. while (( $flag <= ))
  3. do
  4. if (( $flag == ))
  5. then
  6. flag=$[$flag+]
  7. continue
  8. fi
  9. echo "outerFlag=$flag"
  10. for (( innerFlag=; innerFlag < ; innerFlag++ ))
  11. do
  12. if (( $innerFlag == ))
  13. then
  14. flag=$[$flag+]
  15. continue
  16. fi
  17. echo "innerFlag=$innerFlag"
  18. done
  19. done

  以上例子: 当for循环中innerFlag的值为16的时候会跳到外层while循环,当外层循环的flag的值为5的时候,会直接跳过本次循环,然后进入下一次循环,因此在输出的结果中,不会出现outerFlag=5的情况。

接下来可以学习shell学习五:http://www.cnblogs.com/qlqwjy/p/7746009.html

【shell】shell编程(四)-循环语句的更多相关文章

  1. 04 shell编程之循环语句

    Shell编程之循环语句 学习目标: 掌握for循环语句编程 掌握while循环语句编程 目录结构: For循环语句 l  读取不同的变量值,以逐个执行同一组命令 l  For语句结构 for 变量名 ...

  2. shell编程之循环语句for / while / until

    shell编程之循环语句与函数 一.条件测试 二.循环语句 ① for循环语句结构(遍历) 示例1 示例2 ② while循环语句结构(迭代) 示例1 示例2 ③ until 循环语句结构 示例1 一 ...

  3. Shell编程之循环语句与echo的用法

    Shell编程之循环语句与echo的用法 目录 Shell编程之循环语句与echo的用法 一.echo用法 1. echo常用选项 2. 常用的转义字符 3. 特殊符号%.#的用法 二.循环语句 1. ...

  4. shell脚本中select循环语句用法

    shell脚本中select循环语句 1. 脚本中select的语法格式 select VAR in LIST do command1 command2 ... ... commandN done s ...

  5. Shell学习(三)——Shell条件控制和循环语句

    参考博客: [1]Shell脚本的条件控制和循环语句 一.条件控制语句 1.if语句 1.1语法格式: if [ expression ] then Statement(s) to be execut ...

  6. Shell脚本之for循环语句的应用

    在实际工作中,经常会遇到某项任务需要多次执行的情况,而每次执行时仅仅是处理的对象不一样,其他命令相同.这时候可以使用for循环语句,针对不同的取值重复执行相同的命令序列. for循环语句的语法结构: ...

  7. bash 编程中循环语句用法

    1.if 是单分支语句,使用格式如下: if condition ; then statement ….. fi 2.if … else 是双分支语句,使用格式如下: if condition ; t ...

  8. SQl Server Tsql基本编程 ,循环语句 ,存储过程

    一些比较重要但是不一定经常用的 句子 Tsql定义变量 declare @a int :  定义的变量前面必须用@,数据类型是SQL里的数据类型,执行的时候要把需要的有关联的代码一起执行,单独执行一条 ...

  9. Linux - 简明Shell编程06 - 循环语句(Loop)

    脚本地址 https://github.com/anliven/L-Shell/tree/master/Shell-Basics 示例脚本及注释 #!/bin/bash # for循环 for fil ...

  10. shell编程之循环语句

    for #! /bin/sh for FRUIT in apple banana pear; do echo "I like $FRUIT" done while #! /bin/ ...

随机推荐

  1. jQuery中Ajax事件beforesend及各参数含义

    Ajax会触发很多事件. 有两种事件,一种是局部事件,一种是全局事件: 局部事件:通过$.ajax来调用并且分配. $.ajax({ beforeSend: function(){ // Handle ...

  2. Bootstrap 原始按钮

    Bootstrap 原始按钮 <!DOCTYPE html><html><head><meta http-equiv="Content-Type&q ...

  3. 【树论 倍增】51nod1709 复杂度分析

    倍增与位运算有很多共性:这题做法有一点像「线段树上二分」和「线段树套二分」的关系. 给出一棵n个点的树(以1号点为根),定义dep[i]为点i到根路径上点的个数.众所周知,树上最近公共祖先问题可以用倍 ...

  4. mysqldump指令说明

    3种形式mysqldump [OPTIONS] database [tables]mysqldump [OPTIONS] -B | --databases [OPTIONS] DB1 [DB2 DB3 ...

  5. Centos7下安装iptables防火墙

    说明:centos7默认使用的firewalld防火墙,由于习惯使用iptables做防火墙,所以在安装好centos7系统后,会将默认的firewall关闭,并另安装iptables进行防火墙规则设 ...

  6. 小数据池 is 和 ==的区别

    小数据池 一.小数据池 1)代码块 python程序是由代码块构成的,一个代码块的文本作为pythont程序执行的单元 官方文档: A Python program is constructed fr ...

  7. ACM-ICPC 2018 沈阳赛区网络预赛 K. Supreme Number

    A prime number (or a prime) is a natural number greater than 11 that cannot be formed by multiplying ...

  8. H.264 Profile-level-id

    基于SIP协议的VOIP通信,该字段通常位于视频协商sdp报文中,如: video RTP/AVP rtpmap: H264/ fmtp: profile-level-id=42801E; packe ...

  9. POJ 1160 四边形不等式优化DP Post Office

    d(i, j)表示用i个邮局覆盖前j个村庄所需的最小花费 则有状态转移方程:d(i, j) = min{ d(i-1, k) + w(k+1, j) } 其中w(i, j)的值是可以预处理出来的. 下 ...

  10. 03007_HttpServlet

    1.创建 new---Servlet package com.gzdlh.servlet; import java.io.IOException; import javax.servlet.Servl ...