for 循环也是一种shell 循环构造,。for 循环不同于while 和until 循环,因为在循环中,它提供了一种处理序列的方式。这证明在编程时非常有用。因此在bash 脚本中,for 循环是非常流行的构造。实现一个for 循环,很自然的,要用for 命令。在现代版的bash 中,有两种可用的for 循环格式。
for:传统shell 格式
原来的for 命令语法是:
for variable [in words]; do
commands
done
这里的variable 是一个变量的名字,这个变量在循环执行期间会增加,words 是一个可选的条目列表,其值会按顺序赋值给variable,commands 是在每次循环迭代中要执行的命令。在命令行中for 命令是很有用的。我们可以很容易的说明它是如何工作的:
[me@linuxbox ~]$ for i in A B C D; do echo $i; done
A
B
C
D
这个例子中,for 循环有一个四个单词的列表:“A”,“B”,“C”,和“D”。由于这四个单词的列表,for 循环会执行四次。每次循环执行的时候,就会有一个单词赋值给变量i。在循环体内,我们有一个echo 命令会显示i 变量的值,来演示赋值结果。正如while 和until 循环,done 关键字会关闭循环。
for 命令真正强大的功能是我们可以通过许多有趣的方式创建words 列表。例如,通过花括号展开:
[me@linuxbox ~]$ for i in {A..D}; do echo $i; done
A
B
C
D
或者路径名展开:
[me@linuxbox ~]$ for i in distros*.txt; do echo $i; done
distros-by-date.txt
distros-dates.txt
distros-key-names.txt
distros-key-vernums.txt
distros-names.txt
distros.txt
distros-vernums.txt
distros-versions.txt
或者命令替换:
#!/bin/bash
# longest-word : find longest string in a file
while [[ -n $1 ]]; do
if [[ -r $1 ]]; then
max_word=
max_len=0
for i in $(strings $1); do
len=$(echo $i | wc -c)
if (( len > max_len )); then
max_len=$len
max_word=$i
fi
done
echo "$1: '$max_word' ($max_len characters)"
fi
shift
done
在这个示例中,我们要在一个文件中查找最长的字符串。当在命令行中给出一个或多个文件名的时候,该程序会使用strings 程序(其包含在GNU binutils 包中),为每一个文件产生一个可读的文本格式的“words”列表。然后这个for 循环依次处理每个单词,判断当前这个单词是否为目前为止找到的最长的一个。当循环结束的时候,显示出最长的单词。
如果省略掉for 命令的可选项words 部分,for 命令会默认处理位置参数。我们将修改 longest-word 脚本,来使用这种方式:
#!/bin/bash
# longest-word2 : find longest string in a file
for i; do
if [[ -r $i ]]; then
max_word=
max_len=0
for j in $(strings $i); do
len=$(echo $j | wc -c)
if (( len > max_len )); then
max_len=$len
max_word=$j
fi
done
echo "$i: '$max_word' ($max_len characters)"
fi
done
正如我们所看到的,我们已经更改了最外围的循环,用for 循环来代替while 循环。通过省略for 命令的words 列表,用位置参数替而代之。在循环体内,之前的变量i 已经改为变量j。同时shift 命令也被淘汰掉了。
for:C语言格式
最新版本的bash 已经添加了第二种格式的for 命令语法,该语法相似于C 语言中的for 语法格式。其它许多编程语言也支持这种格式:
for (( expression1; expression2; expression3 )); do
commands
done
这里的expression1,expression2,和expression3 都是算术表达式,commands 是每次循环迭代时要执行的命令。在行为方面,这相当于以下构造形式:
(( expression1 ))
while (( expression2 )); do
commands
(( expression3 ))
done
expression1 用来初始化循环条件,expression2 用来决定循环结束的时间,还有在每次循环迭代的末尾会执行expression3。
这里是一个典型应用:
#!/bin/bash
# simple_counter : demo of C style for command
for (( i=0; i<5; i=i+1 )); do
echo $i
done
脚本执行之后,产生如下输出:
[me@linuxbox ~]$ simple_counter
0
1
2
3
4
在这个示例中,expression1 初始化变量i 的值为0,expression2 允许循环继续执行只要变量i 的值小于5,还有每次循环迭代时,expression3 会把变量i 的值加1。C 语言格式的for 循环对于需要一个数字序列的情况是很有用处的。