2.27 Shell while
- while 循环是 Shell 脚本中最简单的一种循环,当条件满足时,while 重复地执行一组语句,当条件不满足时,就退出 while 循环。Shell while 循环的用法如下:
while condition
do
statements
done
condition
表示判断条件,statements
表示要执行的语句(可以只有一条,也可以有多条),do
和done
都是 Shell 中的关键字。
- while 循环的执行流程为:
- 先对 condition 进行判断,如果该条件成立,就进入循环,执行 while 循环体中的语句,也就是 do 和 done 之间的语句。这样就完成了一次循环。
- 每一次执行到 done 的时候都会重新判断 condition 是否成立,如果成立,就进入下一次循环,继续执行 do 和 done 之间的语句,如果不成立,就结束整个 while 循环,执行 done 后面的其它 Shell 代码。
- 如果一开始 condition 就不成立,那么程序就不会进入循环体,do 和 done 之间的语句就没有执行的机会。
注意,在 while 循环体中必须有相应的语句使得 condition 越来越趋近于“不成立”,只有这样才能最终退出循环,否则 while 就成了死循环,会一直执行下去,永无休止。
while 语句和 if else 语句中的 condition 用法都是一样的,你可以使用 test 或 [] 命令,也可以使用 (()) 或 [[]]
- while 循环:举例计算从 1 加到 100 的和。
[root@localhost testshell]# touch test14.sh && vi test14.sh
#!/bin/bash
i=1
sum=0
while (( i<=100 ))
do
((sum+=i))
((i++))
done
echo "The sum is :$sum"
#运行结果
[root@localhost testshell]# . test14.sh
The sum is :5050
-
在 while 循环中,只要判断条件成立,循环就会执行。对于这段代码,只要变量 i 的值小于等于 100,循环就会继续。每次循环给变量 sum 加上变量 i 的值,然后再给变量 i 加 1,直到变量 i 的值大于 100,循环才会停止。
i++
语句使得 i 的值逐步增大,让判断条件越来越趋近于“不成立”,最终退出循环。 -
改进上面的例子,计算从 m 加到 n 的值。
#!/bin/bash
read i n
sum=0
while (( i<=n ))
do
((sum+=i))
((i++))
done
echo "The sum is :$sum"
#运行结果
[root@localhost testshell]# . test14.sh
1 100
The sum is :5050
- 实现一个简单的加法计算器,用户每行输入一个数字,计算所有数字的和。
[root@localhost testshell]# touch test15.sh && vi test15.sh
#!/bin/bash
sum=0
echo "请输入要计算的数字,按 Ctrl+D 组合键结束读取"
while read n
do
((sum+=n))
done
echo "The sum is:$sum"
#运行结果
[root@localhost testshell]# . test15.sh
请输入要计算的数字,按 Ctrl+D 组合键结束读取
1 #enter
2
3
4
5
The sum is:15
在终端中读取数据,可以等价为在文件中读取数据,按下 Ctrl+D 组合键表示读取到文件流的末尾,此时 read 就会读取失败,得到一个非 0 值的退出状态,从而导致判断条件不成立,结束循环。
2.28 Shell until
- unti 循环和 while 循环恰好相反,当判断条件不成立时才进行循环,一旦判断条件成立,就终止循环。until 的使用场景很少,一般使用 while 即可。Shell until 循环的用法如下:
until condition
do
statements
done
condition
表示判断条件,statements
表示要执行的语句(可以只有一条,也可以有多条),do
和done
都是 Shell 中的关键字。
- until 循环的执行流程为:
- 先对 condition 进行判断,如果该条件不成立,就进入循环,执行 until 循环体中的语句(do 和 done 之间的语句),这样就完成了一次循环。
- 每一次执行到 done 的时候都会重新判断 condition 是否成立,如果不成立,就进入下一次循环,继续执行循环体中的语句,如果成立,就结束整个 until 循环,执行 done 后面的其它 Shell 代码。
- 如果一开始 condition 就成立,那么程序就不会进入循环体,do 和 done 之间的语句就没有执行的机会。
注意,在 until 循环体中必须有相应的语句使得 condition 越来越趋近于“成立”,只有这样才能最终退出循环,否则 until 就成了死循环,会一直执行下去,永无休止。
- 改造test14.sh代码,求从 1 加到 100 的值
#!/bin/bash
i=1
sum=0
#在 while 循环中,判断条件为((i<=100)),这里将判断条件改为((i>100)),两者恰好相反
until (( i>100 ))
do
((sum+=i))
((i++))
done
echo "The sum is :$sum"
#运行结果
[root@localhost testshell]# . test14.sh
The sum is :5050
2.29 Shell for
- 除了 while 循环和 until 循环,Shell 脚本还提供了 for 循环,它更加灵活易用,更加简洁明了。Shell for 循环有两种使用形式,
2.29.1 C语言风格的 for 循环
- C语言风格的 for 循环的用法如下:
for((exp1; exp2; exp3))
do
statements
done
-
几点说明:
- exp1、exp2、exp3 是三个表达式,其中 exp2 是判断条件,for 循环根据 exp2 的结果来决定是否继续下一次循环;
- statements 是循环体语句,可以有一条,也可以有多条;
- do 和 done 是 Shell 中的关键字。
-
它的运行过程为:
-
先执行 exp1。
-
再执行 exp2,如果它的判断结果是成立的,则执行循环体中的语句,否则结束整个 for 循环。
-
执行完循环体后再执行 exp3。
-
重复执行步骤 2) 和 3),直到 exp2 的判断结果不成立,就结束循环。
-
-
上面的步骤中,2) 和 3) 合并在一起算作一次循环,会重复执行,for 语句的主要作用就是不断执行步骤 2) 和 3)。
-
exp1 仅在第一次循环时执行,以后都不会再执行,可以认为这是一个初始化语句。exp2 一般是一个关系表达式,决定了是否还要继续下次循环,称为“循环条件”。exp3 很多情况下是一个带有自增或自减运算的表达式,以使循环条件逐渐变得“不成立”。
-
例子,计算从 1 加到 100 的和。
[root@localhost testshell]# cp test14.sh test14back2.sh
[root@localhost testshell]# vi test14.sh
#!/bin/bash
sum=0
for ((i=1;i<=100;i++ ))
do
((sum+=i))
done
echo "The sum is :$sum"
#运行结果
[root@localhost testshell]# . test14.sh
The sum is :5050
代码分析:
执行到 for 语句时,先给变量 i 赋值为 1,然后判断 i<=100 是否成立;因为此时 i=1,所以 i<=100 成立。接下来会执行循环体中的语句,等循环体执行结束后(sum 的值为1),再计算 i++。
第二次循环时,i 的值为2,i<=100 成立,继续执行循环体。循环体执行结束后(sum的值为3),再计算 i++。
重复执行步骤 2),直到第 101 次循环,此时 i 的值为 101,i<=100 不再成立,所以结束循环。
- 由此我们可以总结出 for 循环的一般形式为:
for(( 初始化语句; 判断条件; 自增或自减 ))
do
statements
done
2.29.2 for 循环中的三个表达式
-
for 循环中的 exp1(初始化语句)、exp2(判断条件)和 exp3(自增或自减)都是可选项,都可以省略(但分号
;
必须保留)。 -
修改“从 1 加到 100 的和”的代码,省略 exp1:
#!/bin/bash
sum=0
i=1
for ((; i<=100; i++)) #将i=1移到了 for 循环的外面。
do
((sum += i))
done
echo "The sum is: $sum"
- 省略 exp2,就没有了判断条件,如果不作其他处理就会成为死循环,我们可以在循环体内部使用 break 关键字强制结束循环:
#!/bin/bash
sum=0
for ((i=1; ; i++))
do
if(( i>100 )); then
break
fi
((sum += i))
done
echo "The sum is: $sum"
break 是 Shell 中的关键字,专门用来结束循环
- 省略了 exp3,就不会修改 exp2 中的变量,这时可在循环体中加入修改变量的语句。例如:
#!/bin/bash
sum=0
for ((i=1; i<=100; ))
do
((sum += i))
((i++))
done
echo "The sum is: $sum"
- 同时省略三个表达式:实际意义
#!/bin/bash
sum=0
i=0
for (( ; ; ))
do
if(( i>100 )); then
break
fi
((sum += i))
((i++))
done
echo "The sum is: $sum"
2.29.3 Python 风格的 for in 循环
- Python 风格的 for in 循环的用法如下:
for variable in value_list
do
statements
done
variable 表示变量,value_list 表示取值列表,in 是 Shell 中的关键字。
in value_list 部分可以省略,省略后的效果相当于 in $@
- 每次循环都会从 value_list 中取出一个值赋给变量 variable,然后进入循环体(do 和 done 之间的部分),执行循环体中的 statements。直到取完 value_list 中的所有值,循环就结束了。Shell for in 循环举例:
[root@localhost testshell]# touch test16.sh && vi test16.sh
#!/bin/bash
sum=0
for i in 1 3 5 7 9
do
echo $i
((sum+=i))
done
echo "The sum is :$sum"
#运行结果
[root@localhost testshell]# . test16.sh
1
3
5
7
9
The sum is :25
2.29.4 对 value_list 的说明
-
取值列表 value_list 的形式有多种,可以直接给出具体的值,也可以给出一个范围,还可以使用命令产生的结果,甚至使用通配符。
-
1.直接给出具体的值:可以在 in 关键字后面直接给出具体的值,多个值之间以空格分隔,比如1 2 3 4 5、“cn” “www” “com”等。
-
上面的代码中用一组数字作为取值列表,下面我们再演示一下用一组字符串作为取值列表:
#!/bin/bash
sum=0
for i in "cn" "www" "com"
do
echo $i
done
#运行结果
[root@localhost testshell]# . test16.sh
cn
www
com
- 2.给出一个取值范围:给出一个取值范围的具体格式为:
{start..end}
start 表示起始值,end 表示终止值;注意中间用两个点号相连,而不是三个点号,这种形式只支持数字和字母。
#计算从 1 加到 100 的和:
#!/bin/bash
sum=0
for i in {1..100}
do
((sum+=i))
done
echo "The sum is :$sum"
#运行结果
[root@localhost testshell]# . test14.sh
The sum is :5050
#输出从 A 到 z 之间的所有字符:
#!/bin/bash
for c in {A..z}
do
printf "%c" $c
done
[root@localhost testshell]# . test14.sh
ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz
可以发现,Shell 是根据 ASCII 码表来输出的。
-
3.使用命令的执行结果:使用反引号“或者
(
)
都可以取得命令的执行结果,使用
()都可以取得命令的执行结果,使用
()都可以取得命令的执行结果,使用()这种形式,因为它不容易产生混淆。
-
计算从 1 到 100 之间所有偶数的和:
#!/bin/bash
sum=0
for i in $(seq 2 2 100)
do
((sum+=i))
done
echo "The sum is :$sum"
#运行结果
[root@localhost testshell]# . test14.sh
The sum is :2550
seq 是一个 Linux 命令,用来产生某个范围内的整数,并且可以设置步长。
seq 2 2 100
表示从 2 开始,每次增加 2,到 100 结束。
- 列出当前目录下的所有 Shell 脚本文件:
#!/bin/bash
for filename in $(ls *.sh)
do
echo $filename
done
#运行结果
[root@localhost testshell]# . test14.sh
test10.sh
test11.sh
test12.sh
test13.sh
test14_1.sh
test14bach3.sh
。。。
- 4.使用 Shell 通配符:Shell 通配符可以认为是一种精简化的正则表达式,通常用来匹配目录或者文件,而不是文本,有了 Shell 通配符,不使用 ls 命令也能显示当前目录下的所有脚本文件,请看下面的代码:
#!/bin/bash
for filename in *.sh
do
echo $filename
done
#运行结果
[root@localhost testshell]# . test14.sh
test10.sh
test11.sh
test12.sh
test13.sh
test14_1.sh
test14bach3.sh
...
- 5.使用特殊变量:Shell 中有多个特殊的变量,例如 KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 1: #̲、*、
@
、
@、
@、?、$$ 等,在 value_list 中可以使用它们。
[root@localhost testshell]# touch test17.sh && vi test17.sh#!/bin/bashfunction func(){for str in $@do echo $strdone}#或者是直接将函数调用写在脚本中,执行脚本即可func www http com#运行结果[root@localhost testshell]# func www http comwwwhttpcom
- 也可以省略 value_list,省略后的效果和使用
$@
一样
#!/bin/bashfunction func(){for strdo echo $strdone}#运行结果[root@localhost testshell]# func www http comwwwhttpcom
参考文献:
Shell while循环详解
下一篇:Shell学习-11-循环结构(select in、break 、continue)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123683.html