shell编程中经常使用`for ; while ; until ; break ; continue等关键字来实现循环语句。
for循环得语法结构:
for var in list //var是变量,for和in是关键字,list是一个变量的集合,循环的每一次都会将list的一个子项赋值给var
do
commands
done
获取list的方法:
直接填入一个列表
示例:编写list_1.sh脚本文件
[root@shell for_do]# bash list_1.sh mounth is Jan mounth is Feb mounth is Mar mounth is Apr mounth is May [root@shell for_do]# cat list_1.sh #!/bin/bash for var in Jan Feb Mar Apr May //in后面都是列表内容,变量var遍历该列表。 do echo "mounth is $var" done
从变量中读取一个列表:
示例:编写list_2.sh脚本文件
[root@shell for_do]# bash list_2.sh mounth is Jan mounth is Feb mounth is Mar mounth is Apr mounth is May [root@shell for_do]# cat list_2.sh #!/bin/bash list="Jan Feb Mar Apr May" //先定义一个列表,用list变量保存 for var in $list //这里直接用list变量 do echo "mounth is $var" done
从命令中读取一个列表:
[root@shell for_do]# bash list_3.sh mounth is Jan mounth is Feb mounth is Mar mounth is Apr mounth is May [root@shell for_do]# cat list_3.sh #!/bin/bash for var in `cat fsx` //这里使用``来执行命令,命令是显示fsx文件内的内容。这里识别一个列表的元素是依靠空格、换行、制表符等分割符实现。修改分割符的方法:IFS=$' \n' 表示只保留换行;表示只能通过换行来分割 do echo "mounth is $var" done [root@shell for_do]# cat fsx Jan Feb Mar Apr May
IFS:修改分割符
示例:
[root@shell for_do]# bash list_ifs.sh mounth is Jan Feb Mar Apr May [root@shell for_do]# cat list_ifs.sh #!/bin/bash IFS=$';' list="Jan Feb Mar Apr May" for var in $list do echo "mounth is $var" done
这时,分割符只能用“ ; ”来分割。所以上面识别变量只有一个元素,要分开必须使用" ; ",如下:
[root@shell for_do]# bash list_ifs.sh mounth is Jan mounth is Feb mounth is Mar mounth is Apr mounth is May [root@shell for_do]# cat list_ifs.sh #!/bin/bash IFS=$';' list="Jan;Feb;Mar;Apr;May" for var in $list do echo "mounth is $var" done
从目录读取一个列表:
与前三种不同,for
循环支持读取一个目录,将目录内容作为循环列表进行使用。
示例:
[root@shell for_do]# bash list_4.sh /mnt/for_do [root@shell for_do]# cat list_4.sh #!/bin/bash for var in /mnt/for_do do echo "$var" done //上面的形式时错误的,因为这样,内核不识别/mnt/for_do为一个目录,认为它是一个字符串,所以,要让内核识别为一个目录,要使用文件的通配符号 * ,即:/mnt/for_do/*。 //这里面的通配符使用和使用`ls`命令时使用的一样 [root@shell for_do]# bash list_4.sh /mnt/for_do/fsx /mnt/for_do/list_1.sh /mnt/for_do/list_2.sh /mnt/for_do/list_3.sh /mnt/for_do/list_4.sh /mnt/for_do/list_ifs.sh [root@shell for_do]# cat list_4.sh #!/bin/bash for var in /mnt/for_do/* //此处使用了通配符 * ;所以上面可以输出/mnt/for_do/ 下的所有文件名 do echo "$var" done
第二种for
循环使用结构:
for ((i=1;i<10;i++)) //注意这里是双括号
do
commands
done
示例:
[root@shell for_do]# bash list_5.sh test number is 0 99 test number is 1 98 test number is 2 97 test number is 3 96 test number is 4 95 [root@shell for_do]# cat list_5.sh #!/bin/bash for((i=0,j=99;i<5;i++,j--)) do echo "test number is $i $j" done //shell中for循环判断条件支持多个变量,用逗号隔开
while和until十分相似,这里对比着进行解释。
while的基本语法结构:
while test command //test测试command是否执行成功
do
commands
done
while:直到后面条件成功时,才进入循环
until的基本语法结构:
until test command
do
commands
done
until:直到后面条件成功时,才退出循环
while示例:
[root@shell while_until]# bash test_1.sh 1 2 3 4 [root@shell while_until]# cat test_1.sh #!/bin/bash var=1 while [ $var -lt 5 ] //test可以用[]代替,即当var变量的值小于5时,进入循环。'-lt'是小于 do echo "$var" var=$[ $var+1 ] //var变量值每次加1,是expr命令,可以用[]代替 done
unti示例:
[root@shell while_until]# bash test_2.sh 1 2 3 4 [root@shell while_until]# cat test_2.sh #!/bin/bash var=1 until [ $var -eq 5 ] //当变量等于5时,循环才退出 do echo "$var" var=$[ $var+1 ] done
如果条天永远不成立,会变成死循环
基于for循环的基本语法,可以在里面继续嵌套。
示例:
[root@shell while_until]# bash test_3.sh test number i is 0 test number j is 1 test number j is 2 test number i is 1 test number j is 1 test number j is 2 test number i is 2 test number j is 1 test number j is 2 test number i is 3 test number j is 1 test number j is 2 test number i is 4 test number j is 1 test number j is 2 [root@shell while_until]# cat test_3.sh #!/bin/bash for (( i=0;i<5;i++)) do echo "test number i is $i" for ((j=1;j<3;j++)) do echo "test number j is $j" done done
while嵌套也一样:
[root@shell while_until]# bash test_4.sh test number i is 0 test number j is 1 test number j is 2 test number i is 1 test number j is 1 test number j is 2 test number i is 2 test number j is 1 test number j is 2 test number i is 3 test number j is 1 test number j is 2 test number i is 4 test number j is 1 test number j is 2 [root@shell while_until]# cat test_4.sh #!/bin/bash i=0 while [ $i -lt 5 ] do echo "test number i is $i" for (( j=1;j<3;j++)) do echo "test number j is $j" done i=$[ $i + 1 ] done
我们可以使用break和continue来实现指定环境下的循环控制。
break示例:
[root@shell while_until]# bash test_5.sh test number is 1 test number is 2 [root@shell while_until]# cat test_5.sh #!/bin/bash for (( i=1;i<5;i++)) do if [ $i -eq 3 ] then break; fi echo "test number is $i" done //当for循环执行到i=3时,进入循环,但是if判断到,i变量等于3,进入if语句,break直接跳出循环,所以不再执行其他。
continue示例:
[root@shell while_until]# bash test_6.sh test number is 1 test number is 2 test number is 4 [root@shell while_until]# cat test_6.sh #!/bin/bash for (( i=1;i<5;i++)) do if [ $i -eq 3 ] then continue; fi echo "test number is $i" done //当遇到continue,就不在继续执行当前一步骤的循环,而直接进入下一个步骤的循环。对于本示例就是,当i等于3,执行if语句,遇到continue,就不再执行echo命令,而直接进行下一个循环的i自增,和判断是否for循环条件成立
一个稍微复杂的例子:
通过循环和条件判断,输出指定用户名的/ect/passwd
的配置:
先每行遍历循环,定义变量row,表示每行变量内容;因为每行为一个元素,所以分割符为" \n ",即换行符号
在嵌套一个循环,在每行内进行遍历,定义变量value,表示每行中得单个元素,因为以" ; "间隔,所以分割符为" ; "
在对某一行进行遍历的时候,我们知道其中第一个元素时用户名;即遍历的是第一个元素,且(&&)该元素名==输入的用户名,则匹配到。
匹配到,得有一个标识记录,这里用is_target记录(为0表示没有匹配到,为1表示匹配到)
if判断,如果is_target=1,则输出row变量信息,跳出循环。
[root@shell while_until]# cat test_7.sh #!/bin/bash echo "please input a user name" read uname IFS=$'\n' for row in `cat /etc/passwd` do IFS=$':' i=1 is_target=0 for value in $row do if [ $i -eq 1 ] && [ $value = $uname ] then is_target=1 fi i=$[ $i + 1 ] done if [ $is_target -eq 1 ] then echo $row break; fi done
测试结果:
[root@shell while_until]# bash test_7.sh please input a user name root root x 0 0 root /root /bin/bash [root@shell while_until]# bash test_7.sh please input a user name fsx fsx x 500 500 /home/fsx /bin/bash [root@shell while_until]# bash test_7.sh please input a user name nobody nobody x 99 99 Nobody / /sbin/nologin
总结:综合运用了条件判断,和循环使用