[root@linuxidc ~]# let i=1,sum=0;while [ $i -le 10 ];do let sum=sum+i;let ++i;done;echo $sum 55
在此例中,test_cmd_list中只有一个命令[ $i -le 10 ],所以它的状态直接决定整个循环何时退出。
test_cmd_list中可以是多个命令,但千万要考虑清楚,是否要让决定退出循环的测试命令处在列表的尾部,否则将进入无线循环。
[root@linuxidc ~]# let i=1,sum=0;while echo $i;[ $i -le 10 ];do let sum=sum+i;let ++i;done;echo $sum 1 2 3 4 5 6 7 8 9 10 11 55
对于while循环,有另外两种常见的写法:
(1).test_cmd_list部分使用一个冒号":"或者true命令,使得while进入无限循环。
while :;do # 或者"while true;do"
...
done
(2).使用read命令从标准输入中按行读取值,然后保存到变量line中(既然是read命令,所以可以保存到多个变量中),读取一行是一个循环。
由于标准输入既可以来源于重定向,也可以来源于管道(本质还是重定向),所以有几种常见的写法:
写法一:使用管道传递内容,这是最烂的写法
echo "abc xyz" | while read field1 field2 # 按IFS分割,并赋给两个变量
do
...
done
写法二:
while read line
do
...
done <<< "abc xyz"
写法三:从文件中读取内容
while read line
do
...
done </path/filename
既然是读取标准输入,于是还可以衍生出几种写法:
方法四:while read var;do ...;done < <(cmd_list) # 采用进程替换
方法五:exec <filename;while read var;do ...;done # 改变标准输入
尽管写法有多种,但注意,它们并不等价。方法一中使用的是管道符号,这使得while语句在子shell中执行,这意味着while语句内部设置的变量、数组、函数等在循环外部都不再生效。例如:
#!/bin/bash echo "abc xyz" | while read line do new_var=$line done echo the variable new_var is null: $new_var?
该脚本的执行结果中,$new_var的值将为空。
使用除写法一外的任意一种写法,在while循环外部都能继续获得while内的环境。例如,使用写法二的here string代替写法一:
#!/bin/bash while read line do new_var=$line done <<< "abc xyz" echo the variable new_var is null: $new_var?
由此可以发现,在上面的5种写法中,大众使用的最广泛写法一其实是最烂的一种,如果没注意写法一中while是在子shell运行,很可能会一直疑惑,为什么在while循环里设置好的变量或数组在循环一结束就成了空值呢。
1.7 循环结构:untiluntil和while循环基本一致,所不同的仅仅只是test_cmd_list的意义。
语法结构:
until test_cmd_list; do cmd_list; done
首先判断test_cmd_list中的最后一个命令,如果状态码为非0,则执行一次cmd_list,然后再返回循环的开头再次执行test_cmd_list,直到test_cmd_list的最后一个命令状态码为0时,才退出循环。
和while不同的是,当判断test_cmd_list最后一个命令的状态满足退出条件时直接退出循环,也就是说循环是在test_cmd_list最后一个命令处退出的。
例如: