在 shell 中,重复执行一组命令直到达到某个特定条件的流程控制语句叫循环语句,这期我们就一一介绍。
1. for 语句
格式:
for 变量 in 组或列表
do
命令
done
同 if、case 格式一样,这里的 do 也可以像 then 一样写在第一行的末尾:
for 变量 in 组或列表;do
命令
done
看个例子,这是遍历数组的元素:
[root@server ~]# cat for.sh
#!/bin/bash
a=(1 2 3 4 5)
for i in ${a[@]}
do
echo $i
done
[root@server ~]# sh for.sh
1
2
3
4
5
这是遍历命令的输出中的元素:
[root@server ~]# cat for.sh
#!/bin/bash
for i in $(ls /root/dir/dir1)
do
echo $i
done
[root@server ~]# sh for.sh
b
file1
file2
for 语句还有一种格式,被称为“C语言风格”:
for ((变量定义;变量限制;步进))
do
命令
done
举个例子:
[root@server ~]# cat forc.sh
#!/bin/bash
for ((i=0;i<5;i++))
do
echo $i
done
[root@server ~]# sh forc.sh
0
1
2
3
4
2. IFS(internal field separator)
在使用 for 语句进行遍历时,可能出现一些格式上的问题,比如:
[root@server ~]# cat for-ifs.sh
#!/bin/bash
for i in New Jersey Los Angeles San francisco
do
echo $i
done
[root@server ~]# sh for-ifs.sh
New
Jersey
Los
Angeles
San
francisco
上边的代码输出的结果与预期不符,因为三个城市名内部是有空格的,而 shell 默认把空格,制表符和换行符视为 IFS,即遇到这三个符号时认定一个字段已经结束。怎么解决呢?用双引号把城市名包起来就可以了:
[root@server ~]# cat for-ifs.sh
#!/bin/bash
for i in "New Jersey" "Los Angeles" "San francisco"
do
echo $i
done
[root@server ~]# sh for-ifs.sh
New Jersey
Los Angeles
San francisco
可以临时修改 IFS 的值,在使用后恢复:
[root@server ~]# cat for-ifs.sh
#!/bin/bash
IFS_OLD=$IFS
IFS=:
for i in $(cat ./cities)
do
echo $i
done
IFS=$IFS_OLD
[root@server ~]# cat cities
New Jersey:San Francisco:Los Angeles
[root@server ~]# sh for-ifs.sh
New Jersey
San Francisco
Los Angeles
3. while 语句
while 语句的逻辑是根据命令的返回值来判断是否执行循环体,为 0 (测试通过)则进入。
格式:
while 测试或普通命令
do
命令
done
举个例子:
[root@server ~]# cat while.sh
#!/bin/bash
a=0
while [[ $a -lt 5 ]]
do
echo $a
((++a))
done
[root@server ~]# sh while.sh
0
1
2
3
4
4. until 语句
和 while 相反,测试结果不满足时进入循环体,直到满足才退出循环。
格式:
until 测试或普通命令
do
命令
done
举个例子:
[root@server ~]# cat until.sh
#!/bin/bash
a=0
until [[ $a -ge 5 ]]
do
echo $a
((++a))
done
[root@server ~]# sh until.sh
0
1
2
3
4
5. select 语句
从列表中选择其中之一,执行特定的命令:
格式:
select 变量 in 组或列表
do
命令
done
举个例子:
[root@server ~]# cat select.sh
#!/bin/bash
array=(one two three four five)
select i in {1..5}
do
echo ${array[$i-1]}
done
[root@server ~]# sh select.sh
1) 1
2) 2
3) 3
4) 4
5) 5
#? 1
one
#? 2
two
#? 3
three
#? 4
four
#? 5
five
#? ^C