9.2. while 循环

9.2.1. 是什么?

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 的简单示例

这是一个为不耐烦的人准备的示例

#!/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 目录。每五分钟拍摄一张照片。每小时创建一个新目录,用于保存该小时的图像。每天创建一个新目录,其中包含 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 语句的用法。 这意味着:继续执行,直到我们被强制中断(使用 killCtrl+C)。

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

#!/bin/bash

# This generates a file every 5 minutes

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

请注意使用 date 命令来生成各种文件和目录名。 有关更多信息,请参阅手册页。

Note使用系统
 

前面的示例仅用于演示。 使用系统的 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."

请注意最后几行中的变量是如何保持不带引号的,以便进行算术运算。