本节讲解如何重复一些过程和命令,也就是循环执行一组命令直至到达某个特定条件。bash shell 的循环命令 for、while和until。
(1)for 命令
- 重复执行一些列命令在编程中很常见。通常需要重复一组命令直直至到达某个特定条件,比如处理某个目录下的所有文件、系统上的所有用户或某个文本文件中的所有行。
- bash shell 提供了for命令,运行你创建一个遍历一系列值的循环。每个迭代都通过一个该系列中的值执行一组预定义的命令。bash shell 中的 for命令的基本格式如下:
for var in list
do
commands
done
- 在list参数中,提供了迭代中要用到的一系列值。我们可以通过几种不同的途径来指定列表中的值。
- 在每次迭代过程中,变量var存放着列表中的当前值。第一次迭代会使用列表中的第一个值,第二次迭代会使用列表中的第二个值,以此类推,直到列表中的所有值都被遍历一遍。
- do 和 done 语句之间输入的命令可以是一条或多条标准的bash shell 命令。在这些命令执行中,$var变量包含着这次迭代对应的列表中的某个当前值。
- 前面我们提到有几种不同的方式来指定列表中的值。下面详解介绍各种方式:
读取列表中的值
for 命令最基本的用法就是遍历for命令自身中定义的一系列值:
#!/bin/bash for var1 in xiaoyu1 xiaoyu2 xiaoyu3 do echo "The next state is $var1" done
每次for命令遍历提供值的列表时,它会将列表中的某个值赋值给 $var1 变量。$var1变量像for命令语句中的任何其他脚本变量一样使用。在最后一次迭代后,$var1 变量的值会在shell脚本的剩余部分一直有效。它会一直保持最后一次迭代的值(除非你修改了它):
#!/bin/bash for var1 in xiaoyu1 xiaoyu2 xiaoyu3 do echo "The next state is $var1" done echo "The last state we visited was $var1" var1=HelloWorld echo "Now the value is $var1"
- $var1 变量保持了它的值,也允许我们修改它的值并在 for 命令循环之外跟其他变量一样使用。
读取列表中的复杂值
在使用for命令时会遇到如下问题:
#!/bin/bash for var1 in I don't know if this'll work do echo "word:$var1" done
运行结果是:
$./badtest1 word:I word:dont know if thisll word:work
这个例子中,由于shell看到了列表中的单引号并尝试使用它们来定义一个单独的数据值,从而引起错误。这个问题有两种解决办法:
- 使用转义字符(反斜线)来将单引号转义;
使用双引号来定义用到单引号的值
#!/bin/bash for var1 in I don\'t know if "this'll" work do echo "word:$var1" done
在第一个有问题的值上,添加了反斜线字符来转义don’t值中的单引号。在第二个有问题的值上,将this’ll值用双引号圈起来。两种方法都能正常工作,辨别出这个值。
你还可能遇到的另一个问题是有多个词的值。注意,for 循环假定每个值都是用空格分割的。如果有包含空格的数据值,则可能出问题:
#!/bin/bash for var1 in New Mexico New York do echo "Now going to $var1" done
运行结果:
Now going to New Now going to Mexico Now going to New Now going to York
- 这不是我们想要的结果。for 命令用空格来划分列表中的每个值。如果在单独的数据值中有空格,那么你必须用双引号将这些值圈起来。注意,当你在某个值两边使用双引号时,shell 不会将双引号当成值的一部分。
从变量读取列表
通常shell脚本中,一般将一系列值都集中存储在一个变量中,然后需要变量整个列表。这种情况也可以使用 for 命令:#!/bin/bash list="xiaoyu1 xiaoyu2 xiaoyu3" list=$list" xiaoyu" for var1 in $list do echo "The next user is $var1" done
$list变量包含了给迭代用的标准文本值列表。注意,代码中还使用了另一个赋值语句来向$list变量包含的列表里添加了一个值。这是向变量中存储的已有文本字符串中添加文本的一个常用方法。
从命令读取值
可以使用反引号来执行任何能产生输出的命令,然后在for 命令中使用该命令的输出:#!/bin/bash file="users" for var1 in `cat $file` do echo "The next user is $var1" done
- 注意这种方式,数据中如果有空格,然后会有问题(后续有解决方案)。
- 注意:上例中将文件名赋值给变量,只用了文件名而非路径。这要求文件和脚本位于同一个目录中。否则,需要使用全路径名(不管是相对路径还是绝对路径)来引用文件位置。
- 更改字段分隔符
(3)while 命令
echo "-----while-----"
i=10;
while [[ $i -gt 5 ]]
do
echo $i
((i--))
done
(4)break
echo "-------break---"
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字是 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的,游戏结束!"
break
;;
esac
done
(4)until 命令
(5)嵌套循环
(6)循环处理文件数据
(7)控制循环
(8)处理循环的输出
(9)小结