高级Bash脚本编程指南(16):循环与分支
成于坚持,败于止步
嵌套循环
嵌套循环就是在一个循环中还有一个循环, 内部循环在外部循环体中. 在外部循环的每次执行过程中都会触发内部循环, 直到内部循环执行结束.外部循环执行了多少次, 内部循环就完成多少次.当然, 无论是内部循环还是外部循环的break语句都会打断处理过程.
#!/bin/bash
# nested-loop.sh: 嵌套的"for"循环.
outer=1 # 设置外部循环计数.
# 开始外部循环.
for a in 1 2 3 4 5
do
echo "Pass $outer in outer loop."
echo "---------------------"
inner=1 # 重置内部循环计数.
# ===============================================
# 开始内部循环.
for b in 1 2 3 4 5
do
echo "Pass $inner in inner loop."
let "inner+=1" # 增加内部循环计数.
done
# 内部循环结束.
# ===============================================
let "outer+=1" # 增加外部循环的计数.
echo # 每次外部循环之间的间隔.
done
# 外部循环结束.
exit 0
结果:
root@ubuntu:~/resource/shell-study/0613-2013# chmod +x nested-loop.sh
root@ubuntu:~/resource/shell-study/0613-2013# ls
nested-loop.sh
root@ubuntu:~/resource/shell-study/0613-2013# ./nested-loop.sh
Pass 1 in outer loop.
---------------------
Pass 1 in inner loop.
Pass 2 in inner loop.
Pass 3 in inner loop.
Pass 4 in inner loop.
Pass 5 in inner loop.
Pass 2 in outer loop.
---------------------
Pass 1 in inner loop.
Pass 2 in inner loop.
Pass 3 in inner loop.
Pass 4 in inner loop.
Pass 5 in inner loop.
Pass 3 in outer loop.
---------------------
Pass 1 in inner loop.
Pass 2 in inner loop.
Pass 3 in inner loop.
Pass 4 in inner loop.
Pass 5 in inner loop.
Pass 4 in outer loop.
---------------------
Pass 1 in inner loop.
Pass 2 in inner loop.
Pass 3 in inner loop.
Pass 4 in inner loop.
Pass 5 in inner loop.
Pass 5 in outer loop.
---------------------
Pass 1 in inner loop.
Pass 2 in inner loop.
Pass 3 in inner loop.
Pass 4 in inner loop.
Pass 5 in inner loop.
root@ubuntu:~/resource/shell-study/0613-2013#
影响循环行为的命令
break和continue这两个循环控制命令与其他语言的类似命令的行为是相同的.
break命令用来跳出循环, 而continue命令只会跳过本次循环,忽略本次循环剩余的代码, 进入循环的下一次迭代.
看一个实例来做说明,首先适用于continue,观察输出结果
#!/bin/bash
LIMIT=19 # 上限
echo "Printing Numbers 1 through 20 (but not 3 and 11)."
a=0
while [ $a -le "$LIMIT" ]
do
a=$(($a+1))
if [ "$a" -eq 3 ] || [ "$a" -eq 11 ] # 除了3和11.
then
continue # 跳过本次循环剩余的语句.
fi
echo -n "$a " # 在$a等于3和11的时候,这句将不会执行.
done
echo
exit 0
结果:
root@ubuntu:~/resource/shell-study/0613-2013# ./test1.sh
Printing Numbers 1 through 20 (but not 3 and 11).
1 2 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20
root@ubuntu:~/resource/shell-study/0613-2013#
同样的代码,只是将continue改为break,再次观察输出结果:
#!/bin/bash
LIMIT=19 # 上限
echo "Printing Numbers 1 through 20 (but not 3 and 11)."
a=0
while [ $a -le "$LIMIT" ]
do
a=$(($a+1))
if [ "$a" -eq 3 ] || [ "$a" -eq 11 ] # 除了3和11.
then
break # 跳过本次循环剩余的语句.
fi
echo -n "$a " # 在$a等于3和11的时候,这句将不会执行.
done
echo
exit 0
结果:
root@ubuntu:~/resource/shell-study/0613-2013# ./test1.sh
Printing Numbers 1 through 20 (but not 3 and 11).
1 2
root@ubuntu:~/resource/shell-study/0613-2013#
说明break是程序跳出循环,之后的循环过程无法得到执行,
break命令还可以带一个参数,一个不带参数的break命令只能退出最内层的循环,而break N可以退出N层循环.
首先,作为对比先看一个使用break不带参数的实例:
#!/bin/bash
for outerloop in 1 2 3 4 5
do
echo -n "Group $outerloop: "
# --------------------------------------------------------
for innerloop in 1 2 3 4 5
do
echo -n "$innerloop "
if [ "$innerloop" -eq 3 ]
then
break
fi
done
# --------------------------------------------------------
echo
done
echo
exit 0
结果:
root@ubuntu:~/resource/shell-study/0613-2013# chmod +x test2.sh
root@ubuntu:~/resource/shell-study/0613-2013# ./test2.sh
Group 1: 1 2 3
Group 2: 1 2 3
Group 3: 1 2 3
Group 4: 1 2 3
Group 5: 1 2 3
root@ubuntu:~/resource/shell-study/0613-2013#
内部循环每次遇到判断条件符合要求则结束本次循环,开始新一轮的循环,此时break不带参数,默认只跳出一层循环,试一试break加参数方法吧:
#!/bin/bash
for outerloop in 1 2 3 4 5
do
echo -n "Group $outerloop: "
# --------------------------------------------------------
for innerloop in 1 2 3 4 5
do
echo -n "$innerloop "
if [ "$innerloop" -eq 3 ]
then
break 2
fi
done
# --------------------------------------------------------
echo
done
echo
exit 0
结果:
root@ubuntu:~/resource/shell-study/0613-2013# ./test2.sh
Group 1: 1 2 3
root@ubuntu:~/resource/shell-study/0613-2013#
这一点有别于c或者c++等编程语言,在c中break没有这种带参数的用法,在c语言中,break语句通常用在循环语句和开关语句中。当break用于开关语句switch中时,可使程序跳出switch而执行switch以后的语句;如果没有break语句,则将成为一个死循环而无法退出。break在switch 中的用法十分常见。当break语句用于do-while、for、while循环语句中时,可使程序终止循环而执行循环后面的语句, 通常break语句总是与if语句联在一起。即满足条件时便跳出循环。注意:
1) break语句对if-else的条件语句不起作用。
2) 在多层循环中, 一个break语句只向外跳一层。
continue命令也可以象break命令一样带一个参数,一个不带参数的continue命令只会去掉本次循环的剩余代码.而continue N将会把N层循环的剩余代码都去掉, 但是循环的次数不变.
与break相比似乎不是那么容易理解,为什么说循环的次数不变呢?看看实例吧!有助于你来理解这句话:
#!/bin/bash
# "continue N" 命令, 将让N层的循环全部被continue.
for outer in I II III IV V # 外部循环
do
echo; echo -n "Group $outer: "
# --------------------------------------------------------------------
for inner in 1 2 3 4 5 6 7 8 9 10 # 内部循环
do
if [ "$inner" -eq 7 ]
then
continue
fi
if [ "$inner" -eq 1 ]
then
echo -n " $inner "
else
echo -n "$inner "
fi
done
# --------------------------------------------------------------------
# 译者注: 如果在此处添加echo的话, 当然也不会输出.
done
echo
exit 0
结果:
root@ubuntu:~/resource/shell-study/0613-2013# ./test3.sh
Group I: 1 2 3 4 5 6 8 9 10
Group II: 1 2 3 4 5 6 8 9 10
Group III: 1 2 3 4 5 6 8 9 10
Group IV: 1 2 3 4 5 6 8 9 10
Group V: 1 2 3 4 5 6 8 9 10
root@ubuntu:~/resource/shell-study/0613-2013#
这里continue没有带参数,我们比较容易理解,使用不带参数的continue只是跳过了当前所在循环的某一次循环,不会影响到外层其他循环体,现在使用带参数的continue来看看是什么样子?
#!/bin/bash
# "continue N" 命令, 将让N层的循环全部被continue.
for outer in I II III IV V # 外部循环
do
echo; echo -n "Group $outer: "
# --------------------------------------------------------------------
for inner in 1 2 3 4 5 6 7 8 9 10 # 内部循环
do
if [ "$inner" -eq 7 ]
then
continue 2
fi
if [ "$inner" -eq 1 ]
then
echo -n " $inner "
else
echo -n "$inner "
fi
done
# --------------------------------------------------------------------
# 译者注: 如果在此处添加echo的话, 当然也不会输出.
done
echo
exit 0
结果:
root@ubuntu:~/resource/shell-study/0613-2013# ./test3.sh
Group I: 1 2 3 4 5 6
Group II: 1 2 3 4 5 6
Group III: 1 2 3 4 5 6
Group IV: 1 2 3 4 5 6
Group V: 1 2 3 4 5 6
root@ubuntu:~/resource/shell-study/0613-2013#
也许乍看之下你感觉还是有点不解,不过,很快你就又转回来了,还是比较好理解的,
上面的实例continue带的参数是“2”,当遇到continue的时候,首先最里层循环接收到消息,跳过这个循环,不过,外层循环发话了,先别动,我也收到了消息,我看看让我干什么再说,外层循环这么一看,让我跳出本次循环,开始下一次循环,然后,外层循环拉着正准备跳过这次循环开始下一次循环的内层循环,说“别瞎忙活啦,此次行动作罢,接到上级最新指示,开始下一次循环,赶紧跟我走,时间紧迫”O(∩_∩)O于是乎内层循环后面那些苦苦等待的循环就这样无情的被抛弃了,所以你看到了上面的结果,但是外层循环是受益的,他的每次循环都得到了执行,并且他更高效率的完成了任何,所以这就是上面说的,循环的次数没有变了。
书上同时给出了一个continue N在实际使用时的过程,这里我直接break了,因为这个实例是在不利于初学者去理解,当然等你学有所成,随时可以回头看看这个实例
continue N结构如果用在有意义的场合中, 往往都很难理解, 并且技巧性很高. 所以最好的方法就是尽量避免使用它.
先到这里了,O(∩_∩)O~
我的专栏地址:http://blog.csdn.net/column/details/shell-daily-study.html
待续。。。。