高级Bash脚本编程指南(16):循环与分支

高级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

待续。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值