Shell脚本中的循环 gaunthan Posted on Jul 12 2016 ? ShellScript ? ## for循环 与大多数循环不同,for循环在每次循环执行之后不会对变量进行测试,而是从一个序列开始,遍历序列中的每一个元素直到终点。这一特点让for成为了最具确定性的循环结构,但并不意味着序列中的元素必须在脚本中显式地写出来(尽管可以且经常这样做)。for循环能够遍历文件中的每个单词、变量中的内容,甚至是其他命令的输出。然而,它的最简形式是给出一个要遍历的元素集合: ``` for number in 1 2 3 4 5 do echo -n "$number " # 不自动换行 done echo "" strings="Hi Hello Bye" for str in $strings; do echo $str done ``` 运行结果如:  ### 使用时机 在已知要对一个元素集合执行相同操作,而不是重复执行某个操作直到满足某个条件时,使用for循环最合适。用文件集合或者总是用相同的输入集合执行相同操作,这样的任务也比较适合使用for循环。如果需要在某些测试或者其他结果的基础上中断循环,则for循环就不那么适用了。 ### 向for提供数据 for的输入可以是变量的值: ``` for param in $* do echo "I got a parameter : $param" done ``` 这样便可以灵活地编写更具交互性的脚本。for循环可以从用户获取输入,可以交互地读取输入或者从命令行本身读取。 还有一种方式处理命令行参数。因为语法中的`in list`部分是可选的,故下面的脚本和上面的脚本的一样的: ``` for param do echo "I got a parameter : $param" done ``` 这一技术还适用于函数。 另外值得注意的是标准bash的for循环能处理没有输入的情况。在这种情况下循环体不会得到执行。 ### C风格的for循环 bash shell还具有C风格的for循环: ``` #!/bin/bash for ((i = 1, sum = 0; i <= 10; i++)) do sum=`expr $sum + $i`; # Using "let sum=$sum+$i" is available too. done echo "sum of \"1 + 2 + . . . + 10\" is $sum" ``` ## while循环 while循环在满足条件为真的情况下执行循环体中的代码。这在无法预测满足条件的时刻时非常有用。while还可以用于一直执行某种操作直到满足某个条件为止。while循环的结构是首先定义循环条件,然后是条件为真时执行的代码: ``` while [ condition is true ] do something done ``` ### 使用时机 在没有需要遍历的列表但在具有决定循环何时结束的可测试条件时,使用while最合适。数学计算、时间比较以及当前进程的外部状态都适于使用while循环。持续显示选项并读取用户输入的菜单系统也适合使用while循环。例如,当用户选择“quit”选项时退出菜单。另一方面,如果要对固定的列表进行操作,for循环可能更合适。 ### 用法 while循环最常用的特性是测试循环本身的变化。另一个常见用法是逐行读取文本文件的内容。while可以使用一些方法实现更多的功能,其中之一是从文本行中读取多个单词。这种方法使用`read`工具,将每个单词匹配到一个变量。所有多余的单词都被赋值到最后一个变量。 ## 嵌套循环 一个循环可以存在于另一个循环中,它们甚至可以是不同种类的循环。尽管循环嵌套的层数没有实际限制,但是代码缩进会变得复杂起来,并且很快会难以跟踪循环的终止位置。while循环最适于持续运行知道用户输入单词quit退出循环。在while循环内部,for最适于遍历固定的元素集合。 ## 循环的退出与继续 有时候需要在中途退出循环,这时可以使用`break`命令实现循环的中途退出。该shell内置命令使程序从最内层的循环中退出。可以通过传递数值参数指定更高层的退出。默认参数为1,表示当前循环。`break 2`将从最内层循环中退出,同时退出包含它的外层循环。`break 3`将退出第2层循环外的循环,依此类推。 与`break`命令配套的是`continue`命令,它也是shell内置命令。`continue`与`break`有关联,但不是退出当前循环,而是直接跳转到对循环进行控制的条件测试。与`break`类似,可以为`continue`指定数值参数表示要跳转的外层循环层数。 ## 带case的while循环 `case`语句的常见用法是用于while循环中。`case`语句用来决定每次循环迭代要做的操作。循环本身通常使用`break`语句退出。这在不断读取输入直到当前文本行满足某个条件或者输入结束的情况下非常适用。 ## until循环 除了测试条件相反,until循环与while循环在其他方面完全一样。使用它可以增强可读性,并且在某些情况下能让条件语句序列更容易编写。 ## select循环 select循环非常适合于编写菜单。select循环的一个有趣的特点是它根本就没有条件测试,退出循环的唯一方式是使用`break`或`exit`: ``` #!/bin/bash # select.sh select item in one two three four five do if [ ! -z "$item" ];then echo "You chose option number $REPLY which is \"$item\"" else echo "$REPLY is not valid." fi done ``` 用户的任何合法或者非法的输入都赋值给预留变量`$REPLY`。如果输入非法,则`$item`为空。下面是脚本的运行界面:  select使用PS3变量作为提示符。如果PS3变量没有赋值,select显示`#?`作为提示符。另外,和for一样,可以在select中去掉`in list`语句。在这种情况下,select会使用自己所在脚本或函数的`$*`参数。 赏 Wechat Pay Alipay Shell脚本中的条件执行 Shell脚本中的函数和库