流控制 while 和 until 循环
#!/bin/bash
# while-count:display a series of numbers
i=1
while [ $i -le 5 ];do
echo $i
i=$((i+1))
done
echo "Finished!"
while命令的语法结构如下:
while commands;do commands;done
我们可以使用while循环改进上一节中的菜单驱动程序
#!/bin/bash
# while-menu: a menu driven system information program
DELAY=3 # Number of seconds to display results
while [[ $REPLY != 0 ]];do
clear
cat <<- _EOF_
Please Select:
1.Display System Information
2.Display Disk Space
3.Display Home Space Utilization
0.Quit
_EOF_
read -p "Enter selection [0-3] > "
if [[ $REPLY =~ ^[0-3]$ ]];then
if [[ $REPLY == 1 ]];then
echo "Hostname: $HOSTNAME"
uptime
sleep $DELAY
fi
if [[ $REPLY == 2 ]];then
df -h
sleep $DELAY
fi
if [[ $REPLY == 3 ]];then
if [[ $(id -u) == 0 ]];then
echo "Home Spsce Utilization(All Users)"
du -sh /home/*
else
echo "Home Space Utilization($USER)"
du -sh $HOME
fi
sleep $DELAY
fi
else
echo "Invalid entry" >&2
sleep $DELAY
fi
done
echo "Program terminated."
将菜单封装到while循环内,程序可以在用户每次选择后重复展示菜单项。只要REPLY值不为0,重复循环,展示菜单项,给用户又一次进行选择的机会。
而在每次动作结束时,系统执行sleep命令使程序暂停几秒,让用户能看到选择执行的结果,随后程序清空屏幕显示并再次展示菜单项。
一旦REPLY值为0,也就意味着用户选择了推出项,循环终止,程序进一步执行done之后的代码。
跳出循环
bash提供了两种可控制循环内部程序流的内建命令。
break
break命令立即终止循环,程序从循环体后的语句开始执行;
continue
continue命令则会导致程序跳过本次循环剩余的部分,进入下一次新的循环迭代。
#!/bin/bash
# while-menu: a menu driven system information program
DELAY=3 # Number of seconds to display results
while true;do
clear
cat <<- _EOF_
Please Select:
1.Display System Information
2.Display Disk Space
3.Display Home Space Utilization
0.Quit
_EOF_
read -p "Enter selection [0-3] > "
if [[ $REPLY =~ ^[0-3]$ ]];then
if [[ $REPLY == 1 ]];then
echo "Hostname: $HOSTNAME"
uptime
sleep $DELAY
continue
fi
if [[ $REPLY == 2 ]];then
df -h
sleep $DELAY
continue
fi
if [[ $REPLY == 3 ]];then
if [[ $(id -u) == 0 ]];then
echo "Home Spsce Utilization(All Users)"
du -sh /home/*
else
echo "Home Space Utilization($USER)"
du -sh $HOME
fi
sleep $DELAY
continue
fi
if [[ $REPLY == 0 ]];then
break
fi
else
echo "Invalid entry" >&2
sleep $DELAY
fi
done
echo "Program terminated."
以上版本的菜单驱动构建了一个无限循环,利用true命令向while提供退出状态。因为true退出时状态总为0,所以循环永远也不会停止。这是一个常见的脚本技术。
因为循环永远也不会自动停止,所以需要程序员提供在适当的时刻跳出循环的方式。当用户选择为0时,脚本使用break命令来终止循环。
为了使脚本执行更加高效,可以在其他选项执行末端使用continue。在确认用户做出了选择后,continue让脚本跳过了不需要执行的代码。例如,用户选择了1,那么就没必要再验证其他选项了。
until
while命令退出状态不为0时终止循环,而until命令则刚好相反。until命令在退出状态是0的时候终止循环。
#!/bin/bash
# until-count:display a series of numbers
count=1
until [[ $count -gt 5 ]];do
echo $count
count=$((count + 1))
done
echo "Finished."
选择使用while还是until,通常取决于哪种循环能够允许程序员写出最明了的测试表达式。
使用循环读取文件
while和until可以处理标准输入,这让使用while和until循环处理文件成为可能。
#!/bin/bash
# while-read: read lines from a file
while read distro version release;do
printf "Distro:%s\tVersion:%s\tReleases:%s\n" \
$distro \
$version \
$release
done < distros.txt
为将一份文件重定向到循环中,我们可在done语句之后添加重定向操作符。循环使用read命令读取重定向文件中的字段。
在到达文件末端之前,退出状态皆为0。在读取过文件中的最后一行后,read命令退出,此时退出状态变为非0,循环终止。
将标准输出重定向到循环中也是可以的!
#!/bin/bash
# while-read2:read lines from a file
sort -k 1,1 -k 2n distros.txt | while read distro version release;do
printf "Distro:%s\tVersion:%s\tReleased:%s\n" \
$distro \
$version \
$release
done
需要注意的是因为管道是在子shell中进行循环操作。当循环终止时,循环内部新建的变量或者对变量的赋值效果都会丢失
可以关注作者微信公众号,追踪更多有价值的内容!