36. for 循环 – 循环遍历值列表
for 循环允许基于迭代变量重复执行命令序列。 Bash 支持两种 for 循环,“值列表” 和 “传统的” 类似 C 的方法,我们将在后面的部分中讨论。
“值列表” 语法:
for varname in list
do
commands ##Body of the loop
done
for
、in
、do
和done
是关键字list
包含项目列表,该列表可以位于语句中,也可以从包含多个以空格分隔的单词的变量中获取。 如果for
语句中缺少list
,那么 bash 将使用传递到 shell 中的位置参数。varname
是任意 Bash 变量名。
在这种形式中,bash 对列表中的每个项目执行一次主体中包含的命令(在do
和done
之间)。
如果列表包含 5 个项目,则for
循环将总共执行 5 次。 每次执行时,列表中的当前项目将在主体执行之前存储在变量
varname
中。
因此,这个
varname
可以在循环体中处理。
值列表的几种数据来源
以下几个示例展示了如何使用 bashfor
循环 “值列表” 方法。
列表项的静态值
在以下示例中,值列表(Mon, Tue, Wed, Thu 和 Fri
)直接在关键in
之后给出。
$ cat for1.sh
i=1
for day in Mon Tue Wed Thu Fri
do
echo "Weekday $((i++)) : $day"
done
$ ./for1.sh
Weekday 1 : Mon
Weekday 2 : Tue
Weekday 3 : Wed
Weekday 4 : Thu
Weekday 5 : Fri
值列表不应以逗号分隔(错误写法:Mon, Tue, Wed, Thu, Fri
)。 逗号将被视为值的一部分,即 bash 将使用 "Mon,"
而不是 "Mon"
作为值,如下所示。
$ cat for1-wrong1.sh
i=1
for day in Mon, Tue, Wed, Thu, Fri
do
echo "Weekday $((i++)) : $day"
done
$ ./for1-wrong1.sh
Weekday 1 : Mon,
Weekday 2 : Tue,
Weekday 3 : Wed,
Weekday 4 : Thu,
Weekday 5 : Fri
值列表不应包含在引号中。 (错误写法:"Mon Tue Wed Thu Fri"
)。 如果用双引号引起来,它将被视为单个值(而不是 5 个不同的值),如下所示。
$ cat for1-wrong2.sh
i=1
for day in "Mon Tue Wed Thu Fri"
do
echo "Weekday $((i++)) : $day"
done
$ ./for1-wrong2.sh
Weekday 1 : Mon Tue Wed Thu Fri
使用变量作为列表值
您可以将值存储在变量中,并在 for 循环中的in
关键字后面使用该变量,而不是直接在 for 循环中提供值,如以下示例所示。
$ cat for2.sh
i=1
weekdays="Mon Tue Wed Thu Fri"
for day in $weekdays
do
echo "Weekday $((i++)) : $day"
done
$ ./for2.sh
Weekday 1 : Mon
Weekday 2 : Tue
Weekday 3 : Wed
Weekday 4 : Thu
Weekday 5 : Fri
$ cat for2-wrong.sh i=1 weekdays="Mon Tue Wed Thu Fri" for day in "$weekdays" do echo "Weekday $((i++)) : $day" done $ ./for2-wrong.sh Weekday 1 : Mon Tue Wed Thu Fri
从位置参数获取列表值
如果您没有在 bash for 循环中指定关键字in
后跟值列表,它将使用传递给 shell 脚本的位置参数:
$ cat for3.sh
i=1
for day
do
echo "Weekday $((i++)) : $day"
done
$ ./for3.sh Mon Tue Wed Thu Fri
Weekday 1 : Mon
Weekday 2 : Tue
Weekday 3 : Wed
Weekday 4 : Thu
Weekday 5 : Fri
使用此方法时要小心。 指定 for 循环时不应包含关键字in
,因为 bash 会看到一个空列表并且永远不会执行循环。 以下是一个错误例子:
$ cat for3-wrong.sh i=1 for day in do echo "Weekday $((i++)) : $day" done $ ./for3-wrong.sh Mon Tue Wed Thu Fri
使用命令输出作为值列表
您可以使用任何 UNIX/Linux 命令的输出作为 for 循环的值列表,方法是将命令括在反引号 ` `
中,如下例所示。
列出/etc/passwd
文件中的用户名:
$ cat for4.sh
i=1
for username in `awk -F: '{print $1}' /etc/passwd`
do
echo "Username $((i++)) : $username"
done
$ ./for4.sh
Username 1 : ramesh
Username 2 : john
Username 3 : preeti
Username 4 : jason
..
循环遍历文件和目录
您可以使用 for 循环循环遍历特定目录下的文件和目录。 只需cd
到该目录,并在 for 循环中给出*
,如下所示。
循环遍历主目录下的所有文件和目录:
$ cat for5.sh
i=1
cd ~
for item in *
do
echo "Item $((i++)) : $item"
done
$ ./for5.sh
Item 1 : positional-parameters.sh
Item 2 : backup.sh
Item 3 : emp-report.awk
Item 4 : item-list.sed
Item 5 : employee.db
bash for 循环中*
的用法类似于我们在 Linux 命令行中使用ls
命令(以及其他几个命令)的文件通配符。
例如,以下将显示您的主目录下的所有文件和目录。 这是上面for5.sh
示例中使用的概念。
cd ~
ls *
下面将显示/etc
目录下所有以 a、b、c 或 d 开头的 *.conf
文件。
$ ls -1 /etc/[abcd]*.conf
/etc/asound.conf
/etc/autofs_ldap_auth.conf
/etc/cas.conf
/etc/cgconfig.conf
/etc/cgrules.conf
/etc/dracut.conf
用于ls
命令的相同参数可以在 bash for 循环中使用,如下面的示例所示。
$ cat for5-1.sh
i=1
for file in /etc/[abcd]*.conf
do
echo "File $((i++)) : $file"
done
$ ./for5-1.sh
File 1 : /etc/asound.conf
File 2 : /etc/autofs_ldap_auth.conf
File 3 : /etc/cas.conf
File 4 : /etc/cgconfig.conf
File 5 : /etc/cgrules.conf
File 6 : /etc/dracut.conf
跳出 For
循环
您可以使用break
命令跳出 for 循环,如下所示。
$ cat for6.sh
i=1
for day in Mon Tue Wed Thu Fri
do
echo "Weekday $((i++)) : $day"
if [ $i -eq 3 ]; then
break;
fi
done
$ ./for6.sh
Weekday 1 : Mon
Weekday 2 : Tue
继续 for 循环
在某些情况下,您可以忽略 for 循环体中的其余命令,并使用如下所示的continue
命令再次从顶部继续循环(使用列表中的下一个值)。
以下示例将"(WEEKEND)"
添加到 Sat 和 Sun,并将"(weekday)"
添加到其余日期。
$ cat for7.sh
i=1
for day in Mon Tue Wed Thu Fri Sat Sun
do
echo -n "Day $((i++)) : $day"
if [ $i -eq 7 -o $i -eq 8 ]; then
echo " (WEEKEND)"
continue;
fi
echo " (weekday)"
done
$ ./for7.sh
Day 1 : Mon (weekday)
Day 2 : Tue (weekday)
Day 3 : Wed (weekday)
Day 4 : Thu (weekday)
Day 5 : Fri (weekday)
Day 6 : Sat (WEEKEND)
Day 7 : Sun (WEEKEND)
您可能已经注意到,包含第二个echo
的else
语句也会起作用。 通常有多种方法可以完成同一件事。
使用 in
的数字范围
您可以通过在in
关键字后面使用大括号扩展来循环遍历 for 循环中的数字范围。
以下示例循环遍历值 1 到 10。
$ cat for8.sh
for num in {1..10}
do
echo "Number: $num"
done
$ ./for8.sh
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
...
使用 in
递增的数字范围..
以下示例循环访问一组数字,但每次循环变量都会增加 2,而不是 1。 循环将执行五次,因为之后循环变量将超出范围。
从 1 到 10 按 2 循环,即显示从 1 到 10 的奇数:
$ cat for9.sh
for num in {1..10..2}
do
echo "Number: $num"
done
$ ./for9.sh
Number: 1
Number: 3
Number: 5
Number: 7
Number: 9