ITEEDU

9.2. while循环

9.2.1. 什么是while循环?

while 结构允许重复执行一系列命令,只要控制 while 循环的命令执行成功(退出状态是零)。语法是:

while CONTROL-COMMAND; do CONSEQUENT-COMMANDS; done

CONTROL-COMMAND 可以是任何可以返回成功或者失败状态的命令(组)。CONSEQUENT-COMMANDS 可以使任何程序,脚本或者shell结构。

只要 CONTROL-COMMAND 一失败,循环就退出。在一个脚本当中,跟随 done 语句的命令就执行。

返回状态是最后的 CONSEQUENT-COMMANDS 命令的退出状态,如果什么都没有执行就是零。

9.2.2. 例子

9.2.2.1. 使用while的简单例子

这里是一个为 impatient的例子:

#!/bin/bash

# This script opens 4 terminal windows.

i="0"

while [ $i -lt 4 ]
do
xterm &
i=$[$i+1]
done

9.2.2.2. 嵌套while循环

下面的例子是拷贝在web目录中由摄像头生成的图片。每5分钟就生成一张图片。每1个小时,就建立一个新的目录,存放那个小时中的图片。每天一个新的包含24个子目录的目录就被创建。脚本在后台运行。

#!/bin/bash

# This script copies files from my homedirectory into the webserver directory.
# (use scp and SSH keys for a remote directory)
# A new directory is created every hour.

PICSDIR=/home/carol/pics
WEBDIR=/var/www/carol/webcam

while true; do 
	DATE=`date +%Y%m%d`
	HOUR=`date +%H`
	mkdir $WEBDIR/"$DATE"
	
	while [ $HOUR -ne "00" ]; do 
		DESTDIR=$WEBDIR/"$DATE"/"$HOUR"
		mkdir "$DESTDIR"
		mv $PICDIR/*.jpg "$DESTDIR"/
		sleep 3600
		HOUR=`date +%H`
	done
done

注意 true 语句的使用。意味着:直到我们强制中断否则就继续执行。(使用 kill 或者 Ctrl+C)。

这个小脚本可以用来模拟测试;生成文件:

#!/bin/bash

# This generates a file every 5 minutes

while true; do
touch pic-`date +%s`.jpg
sleep 300
done

注意使用 date 命令来生成各种文件和目录名字的用法。更多请见帮助页面。

[注意] Use the system

先前的例子是为了证明。普通的检查能很容易地使用系统自带的 cron 工具来完成。当从crontab来执行的时候不要忘了重定向输出和错误!

9.2.2.3. 使用键盘输入来控制while循环

这个脚本可以由用户用 Ctrl+C 来中断:

#!/bin/bash

# This script provides wisdom

FORTUNE=/usr/games/fortune

while true; do
echo "On which topic do you want advice?"
cat << topics
politics
startrek
kernelnewbies
sports
bofh-excuses
magic
love
literature
drugs
education
topics

echo
echo -n "Make your choice: "
read topic
echo
echo "Free advice on the topic of $topic: "
echo
$FORTUNE $topic
echo

done

一个 here 文档用来提示用户可能的选择项。再次,true 一次又一次地重复测试 CONSEQUENT-COMMANDS 中的命令。

9.2.2.4. 计算一个平均数

这个脚本在运算之前先进行测试,然后计算用户输入的平均数:如果输入不在允许范围内,就打印一条消息。如果按下 q 就退出循环:

#!/bin/bash

# Calculate the average of a series of numbers.

SCORE="0"
AVERAGE="0"
SUM="0"
NUM="0"

while true; do

  echo -n "Enter your score [0-100%] ('q' for quit): "; read SCORE;

  if (("$SCORE" < "0"))  || (("$SCORE" > "100")); then
    echo "Be serious.  Common, try again: "
  elif [ "$SCORE" == "q" ]; then
    echo "Average rating: $AVERAGE%."
    break
  else
    SUM=$[$SUM + $SCORE]
    NUM=$[$NUM + 1]
    AVERAGE=$[$SUM / $NUM]
  fi

done

echo "Exiting."

注意在最后几行中变量是如何解除引用来达到运算的目的。