Shell for循环和for int循环说明
除了 while 循环和 until 循环,Shell 脚本还提供了 for 循环,它更加灵活易用,更加简洁明了。Shell for 循环有两种使用形式,下面我们逐一讲解。 C语言风格的 for 循环的用法如下: for((exp1; exp2; exp3)) do statements done 几点说明: exp1、exp2、exp3 是三个表达式,其中 exp2 是判断条件,for 循环根据 exp2 的结果来决定是否继续下一次循环; statements 是循环体语句,可以有一条,也可以有多条; do 和 done 是 Shell 中的关键字。 它的运行过程为: 1) 先执行 exp1。 2) 再执行 exp2,如果它的判断结果是成立的,则执行循环体中的语句,否则结束整个 for 循环。 3) 执行完循环体后再执行 exp3。 4) 重复执行步骤 2) 和 3),直到 exp2 的判断结果不成立,就结束循环。 上面的步骤中,2) 和 3) 合并在一起算作一次循环,会重复执行,for 语句的主要作用就是不断执行步骤 2) 和 3)。 exp1 仅在第一次循环时执行,以后都不会再执行,可以认为这是一个初始化语句。exp2 一般是一个关系表达式,决定了是否还要继续下次循环,称为“循环条件”。exp3 很多情况下是一个带有自增或自减运算的表达式,以使循环条件逐渐变得“不成立”。 下面我们给出一个实际的例子,计算从 1 加到 100 的和。 #!/bin/bash sum=0 for ((i=1; i<=100; i++)) do ((sum += i)) done echo "The sum is: $sum" 运行结果: The sum is: 5050 代码分析: 1) 执行到 for 语句时,先给变量 i 赋值为 1,然后判断 i<=100 是否成立;因为此时 i=1,所以 i<=100 成立。接下来会执行循环体中的语句,等循环体执行结束后(sum 的值为1),再计算 i++。 2) 第二次循环时,i 的值为2,i<=100 成立,继续执行循环体。循环体执行结束后(sum的值为3),再计算 i++。 3) 重复执行步骤 2),直到第 101 次循环,此时 i 的值为 101,i<=100 不再成立,所以结束循环。 由此我们可以总结出 for 循环的一般形式为: for(( 初始化语句; 判断条件; 自增或自减 )) do statements done for 循环中的三个表达式 for 循环中的 exp1(初始化语句)、exp2(判断条件)和 exp3(自增或自减)都是可选项,都可以省略(但分号;必须保留)。 1) 修改“从 1 加到 100 的和”的代码,省略 exp1: #!/bin/bash sum=0 i=1 for ((; i<=100; i++)) do ((sum += i)) done echo "The sum is: $sum" 可以看到,将i=1移到了 for 循环的外面。 2) 省略 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 中的关键字,专门用来结束循环,后续章节还会深入讲解。 3) 省略了 exp3,就不会修改 exp2 中的变量,这时可在循环体中加入修改变量的语句。例如: #!/bin/bash sum=0 for ((i=1; i<=100; )) do ((sum += i)) ((i++)) done echo "The sum is: $sum" 4) 最后给大家看一个更加极端的例子,同时省略三个表达式: #!/bin/bash sum=0 i=0 for (( ; ; )) do if(( i>100 )); then break fi ((sum += i)) ((i++)) done echo "The sum is: $sum" 这种写法并没有什么实际意义,仅仅是为了给大家做演示。 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 使用特殊变量」将会详细讲解。 每次循环都会从 value_list 中取出一个值赋给变量 variable,然后进入循环体(do 和 done 之间的部分),执行循环体中的 statements。直到取完 value_list 中的所有值,循环就结束了。 Shell for in 循环举例: #!/bin/bash sum=0 for n in 1 2 3 4 5 6 do echo $n ((sum+=n)) done echo "The sum is "$sum The sum is 21 对 value_list 的说明 取值列表 value_list 的形式有多种,你可以直接给出具体的值,也可以给出一个范围,还可以使用命令产生的结果,甚至使用通配符,下面我们一一讲解。 1) 直接给出具体的值 可以在 in 关键字后面直接给出具体的值,多个值之间以空格分隔,比如1 2 3 4 5、"abc" "390" "tom"等。 上面的代码中用一组数字作为取值列表,下面我们再演示一下用一组字符串作为取值列表: #!/bin/bash for str in "C语言中文网" "http://c.biancheng.net/" "成立7年了" "日IP数万" do echo $str done 运行结果: C语言中文网 http://c.biancheng.net/ 成立7年了 日IP数万 2) 给出一个取值范围 给出一个取值范围的具体格式为: {start..end} start 表示起始值,end 表示终止值;注意中间用两个点号相连,而不是三个点号。根据笔者的实测,这种形式只支持数字和字母。 例如,计算从 1 加到 100 的和: #!/bin/bash sum=0 for n in {1..100} do ((sum+=n)) done echo $sum 运行结果: 5050 再如,输出从 A 到 z 之间的所有字符: #!/bin/bash for c in {A..z} do printf "%c" $c done 输出结果: ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz 可以发现,Shell 是根据 ASCII 码表来输出的。 3) 使用命令的执行结果 使用反引号``或者$()都可以取得命令的执行结果,我们在《Shell变量》一节中已经进行了详细讲解,并对比了两者的优缺点。本节我们使用$()这种形式,因为它不容易产生混淆。 例如,计算从 1 到 100 之间所有偶数的和: #!/bin/bash sum=0 for n in $(seq 2 2 100) do ((sum+=n)) done echo $sum 运行结果: 2550 seq 是一个 Linux 命令,用来产生某个范围内的整数,并且可以设置步长,不了解的读者请自行百度。seq 2 2 100表示从 2 开始,每次增加 2,到 100 结束。 再如,列出当前目录下的所有 Shell 脚本文件: #!/bin/bash for filename in $(ls *.sh) do echo $filename done 运行结果: demo.sh test.sh abc.sh ls 是一个 Linux 命令,用来列出当前目录下的所有文件,*.sh表示匹配后缀为.sh的文件,也就是 Shell 脚本文件。 4) 使用 Shell 通配符 Shell 通配符可以认为是一种精简化的正则表达式,通常用来匹配目录或者文件,而不是文本,不了解的读者请猛击《Linux Shell 通配符(glob 模式)》。 有了 Shell 通配符,不使用 ls 命令也能显示当前目录下的所有脚本文件,请看下面的代码: #!/bin/bash for filename in *.sh do echo $filename done 运行结果: demo.sh test.sh abc.sh 5) 使用特殊变量 Shell 中有多个特殊的变量,例如 $#、$*、$@、$?、$$ 等(不了解的读者请猛击《Shell特殊变量》),在 value_list 中就可以使用它们。 #!/bin/bash function func(){ for str in $@ do echo $str done } func C++ Java Python C# 运行结果: C++ Java Python C# 其实,我们也可以省略 value_list,省略后的效果和使用$@一样。请看下面的演示: #!/bin/bash function func(){ for str do echo $str done } func C++ Java Python C# 运行结果: C++ Java Python C# 关注公众号「站长严长生」,在手机上阅读所有教程,随时随地都能学习。 (编辑:银川站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |