说明:本文是对Vamei知乎文章《快速学习Bash》(https://zhuanlan.zhihu.com/p/32692644)一文的学习笔记,根据个人理解调整了内容顺序,补充了一些注释和说明等内容。
4.9 循环结构
循环结构是编程语言中另一种常见的语法结构。循环结构的功能是重复执行某一段代码,直到计算机的状态符合某一条件。
4.9.1 while循环
在while语法中,Bash会循环执行隶属于while的代码块,直到逻辑表达式不成立。比如下面的demo_while.bash:
#!/bin/bash
#demo_while.bash
now=`date +'%Y%m%d%H%M'`
deadline=`date --date='1 hour' +'%Y%m%d%H%M'`
while [ $now -lt $deadline ]
do
date
echo "not yet"
sleep 10
now=`date +'%Y%m%d%H%M'`
done
echo "now, deadline reached"
关键字do和done之间的代码是隶属于该循环结构的代码块。在while后面跟着条件,该条件决定了代码块是否重复执行下去。这个条件是用当前的时间与目标时间对比。如果当前时间小于目标时间,那么代码块就会重复执行下去。否则,Bash将跳出循环,继续执行后面的语句。
如果while的条件始终是真,那么循环会一直进行下去。下面的程序就是以无限循环的形式,不断播报时间:
#!/bin/bash
while true
do
date
sleep 1
done
语法while的终止条件是一个逻辑判断。如果在循环过程中改变逻辑判断的内容,那么我们很难在程序执行之前预判循环进行的次数。正如我们之前在demo_while.bash中看到的,我们在循环进行过程中改变着作为条件的逻辑表达式,不断地更新参与逻辑判断的当前时间。
4.9.2 for循环
与while语法对应的是for循环。这种语法会在程序进行前确定好循环进行的次数,比如demo_for.bash:
#!/bin/bash
for var in `ls log*`
do
rm $var
done
在这个例子中,命令ls log*将返回所有以log开头的文件名。这些文件名之间由空格分隔。循环进行时,Bash会依次取出一个文件名,赋值给变量var,并执行do和done之间隶属于for结构的程序块。由于ls命令返回的内容在是确定的,因此for循环进行的次数也会在一开始确定下来。
在for语法中,我们也可以使用自己构建一个由空格分隔的文本。由空格区分出来的每个子文本会在循环中赋值给变量。比如:
#!/bin/bash
for user in vamei anna yutian
do
echo $user
done
此外,for循环还可以和seq命令配合使用。命令seq用于生成一个等差的整数序列。命令后面可以跟3个参数,第一个参数表示整数序列的开始数字,第二个参数表示每次增加多少,最后一个参数表示序列的终点。因此,下面命令:
$seq 1 2 10
将返回:
1 3 5 7 9
可以看到,seq返回的也是由空格分隔开的文本。因此,seq的返回结果也可用于for循环。
结合for循环和seq命令,我们可以解一些有趣的数学问题。比如高斯求和,是要计算从1到100的所有整数的和。我们可以用Bash解决:
#!/bin/bash
total=0
for number in `seq 1 1 100`
do
total=$(( $total + $number ))
done
echo $total
这个问题还可以用do while循环来求解:
#!/bin/bash
total=0
number=1
while :
do
if [ $number -gt 100 ]
then
break
fi
total=$(( $total + $number ))
number=$(($number + 1))
done
echo $total
这里break语句的作用是在满足条件时跳出循环。
如果想计算1到100所有不被3整数的和,则可以使用continue语句,跳过所有被3整数的数:
#!/bin/bash
total=0
for number in `seq 1 1 100`
do
if (( $number % 3 == 0 ))
then
continue
fi
total=$(( $total + $number ))
done
echo $total