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

for

for循环有两种形式:

for-in语句

基本格式如下:

for var in list
do
commands
done

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

先来一个例子吧:

#!/bin/bash
for str in a b c d e
do
echo $str
done

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

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

#!/bin/bash
list="a,b,c,d,e"
for str in $list
do
echo $str
done

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

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

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

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

#!/bin/bash
#input username and kill relactive process for kill user
echo "please input username for kill"
read username
#if username is root ,exit
if [ ${username} = 'root' ]
then
echo "root can not kill"
exit
fi
#get user PID
PID=`/usr/bin/ps -aux | /usr/bin/grep qlq | /usr/bin/awk '$1="qlq" {print $2}'`
for killpid in $PID
do
kill - $killpid
done
echo "killed ok!"

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

#!/bin/bash
#for xx in xxx usage
for pd in $(/usr/bin/ls /root/sshDemo/)
do
echo $pd
done

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

结果:

[root@VM_0_12_centos sshDemo]# ./testFor.sh
addUserBatch.sh
delUserBatch.sh
killUser.sh
testApache.sh
testFile.sh
testFor.sh
testKuohao.sh
testNum.sh
testSelect.sh
testShift.sh

修改IFS值

#!/bin/bash
#定义一个变量oldIFS保存未修改前的IFS的值
oldIFS=$IFS
#修改IFS值,以逗号为分隔符
IFS=$','
list=a,b,c,d,e
list2="a b c d e"
for var in $list
do
echo $var
done
for var2 in $list2
do
echo $var2
done
#还原IFS的值
IFS=$oldIFS

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

C语言风格的for循环

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

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

一个例子足以说明:

#!/bin/bash
for (( i = ; i <= ; i++ ))
do
echo $i
done

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

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

#!/bin/bash
#adduser batch
echo "please input username:"
read username
echo "please input number to create:"
read number
#start to create user
for(( i=;i<="${number}";i++ ))
do
/usr/sbin/adduser "${username}${i}" > /dev/null > /dev/null
done
#add finished
echo "add OK!"
echo "please input passwd for users"
read password
for(( i=;i<="${number}";i++ ))
do
/usr/sbin/usermod -p "${password}" "${username}${i}" > /dev/null > /de
v/null
done

结果:

[root@VM_0_12_centos sshDemo]# ./addUserBatch.sh
please input username:
ppp
please input number to create: add OK!
please input passwd for users [root@VM_0_12_centos sshDemo]# tail - /etc/passwd
ppp16:x::::/home/ppp16:/bin/bash
ppp17:x::::/home/ppp17:/bin/bash
ppp18:x::::/home/ppp18:/bin/bash
ppp19:x::::/home/ppp19:/bin/bash
ppp20:x::::/home/ppp20:/bin/bash
[root@VM_0_12_centos sshDemo]# tail - /etc/shadow
ppp16::::::::
ppp17::::::::
ppp18::::::::
ppp19::::::::
ppp20::::::::

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

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

#!/bin/bash
#delete user batch
echo "please input username word to delete"
read word
#get All users like word*
users=`/usr/bin/grep ${word} /etc/passwd | awk -F: -v word1=${word} 'index($1,wo
rd1)> {print $}'`
if [ "${users}" = '' ]
then
echo "user is does not exist!"
exit
fi
for username in ${users}
do
/usr/sbin/userdel -rf ${username} > /dev/null >/dev/null
done
if [ "" = "$?" ]
then
echo "delete ok!"
else
echo "delete failed!"
fi

while循环

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

while test command
do
other commands
done
 

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

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

示例一:

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

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

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

示例二:

#!/bin/bash
flag=
while [ $flag -le ]
do
echo $flag
flag=$[$flag + ]
done
 

示例三:

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

结果:

[root@VM_0_12_centos sshDemo]# sh -x testShift.sh
+ '[' -eq ']'
+ sum=
+ '[' -gt ']'
+ sum=
+ shift
+ '[' -gt ']'
+ sum=
+ shift
+ '[' -gt ']'
+ sum=
+ shift
+ '[' -gt ']'
+ sum=
+ shift
+ '[' -gt ']'
+ echo

计算过程:


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

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



until循环语句

until语句基本格式如下:

until test commands
do
other commands
done
 

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

示例:

#!/bin/bash
flag=
until (( $flag > ))
do
echo $flag
flag=$[ $flag + ]
done

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

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

控制循环

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

break

  1. break用于跳出当前循环

示例一:

#!/bin/bash
for (( flag=; flag <= ; flag++ ))
do
if (( $flag == ))
then
break
fi
echo $flag
done
 

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

  1. break用于跳出内层循环

示例二:

#!/bin/bash
flag=
while (( $flag < ))
do
for (( innerFlag=; innerFlag < ; innerFlag++ ))
do
if (( $innerFlag == ))
then
break
fi
echo "innerFlag=$innerFlag"
done
echo "outerFlag=$flag"
done
 

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

...

innerFlag=0

innerFlag=1

outerFlag=0

...

  1. break用于跳出外层循环

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

示例三:

#!/bin/bash
flag=
while (( $flag < ))
do
for (( innerFlag=; innerFlag < ; innerFlag++ ))
do
if (( $innerFlag == ))
then
# 2表示外面一层循环
break
fi
echo "innerFlag=$innerFlag"
done
echo "outerFlag=$flag"
done
 

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

innerFlag=0

innerFlag=1

continue

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

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

示例:

flag=
while (( $flag <= ))
do
if (( $flag == ))
then
flag=$[$flag+]
continue
fi
echo "outerFlag=$flag"
for (( innerFlag=; innerFlag < ; innerFlag++ ))
do
if (( $innerFlag == ))
then
flag=$[$flag+]
continue
fi
echo "innerFlag=$innerFlag"
done
done

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

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

最新文章

  1. SQLBulkCopy使用实例--读取Excel写入数据库/将 Excel 文件转成 DataTable
  2. jquery $.ajax()方法
  3. Asp.net MVC中提交集合对象,实现Model绑定(转载)
  4. android学习笔记22——Notification
  5. 关于表格中td自动换行做法
  6. Javascript之基本包装类型
  7. disconf实践(一)
  8. LVS+Keepalived+Nginx+Tomcat高可用负载均衡集群配置(DR模式,一个VIP,多个端口)
  9. poj3186 Treats for the Cows
  10. UVA - 10057 A mid-summer night&amp;#39;s dream.
  11. Netflix公司监控内部安全的开源项目
  12. WEB安全实战(一)SQL盲注
  13. CodeForces 706A Beru-taxi
  14. CLR VIA C#: 基元类型、 引用类型 和 值类型
  15. 【Beta阶段】第七次scrum meeting
  16. Linux学习记录--文件IO操作相关系统编程
  17. 使用C# 操作存储过程,执行sql语句通用类
  18. HttpServletRequest基础
  19. C#Thread的方法、Start()、Sleep(int)、Abort()、Suspend()、Resume()
  20. vue的一些小坑

热门文章

  1. Mybatis-Generator逆向生成Po,Mapper,XMLMAPPER(idea)
  2. python 实例方法,类方法,静态方法,普通函数
  3. Java中集合类
  4. Bootstrap 表格2
  5. OAuth授权之回调accessToken
  6. Luogu P3727 曼哈顿计划E 点分治+hash
  7. hihoCoder-1089-Floyd
  8. [LUOGU] 3959 宝藏
  9. RN安卓原生模块
  10. 王小胖之 Base64编码/解码