Bash Shell循环

Bash Shell循环,你希望在符合条件的情况下重复执行某些操作。

解决方案

对于算术条件,使用 while 循环:

while (( COUNT < MAX ))
do
    some stuff
    let COUNT++
done

对于文件系统相关的条件:

while [ -z "$LOCKFILE" ]
do
    some things
done

对于读取输入:

while read lineoftext
do
    process $lineoftext
done

讨论

第一个 while 语句中的双括号界定了算术表达式,这很像 shell 变量赋值中用到的 $(())。双括号内出现的变量名表示取值。也就是说,不需要写成 $VAR,直接在括号中使用 VAR 就行了。

while [ -z"$LOCKFILE" ] 中的方括号和 if 语句中的一样,等同于使用 test 命令。

最后的示例 while read lineoftext 没有用到任何括号、方括号或花括号。在 bash 中,while 语句的语法是这么定义的:该语句的条件是一系列要执行的命令(就像 if 语句),最后一个命令的退出状态决定了条件是真还是假。退出状态为 0,表示真;否则,表示假。

如果顺利读取,read 返回 0;如果读到文件末尾,则返回 1。这意味着,对于前者,while 视其为真;对于后者,while 视其为假并停止循环。然后接着执行 done 之后的语句。

“当命令返回 0 时继续循环”这种逻辑似乎有点颠倒了,因为大多数类 C 语言采用的是与此相反的逻辑,也就是“非 0 时循环”。但在 shell 中,为 0 的返回值表示一切顺利;而非 0 的返回值则表示错误退出。

(()) 也是如此。shell 会对其中的表达式求值,如果结果为非 0,那么 (()) 就返回 0;如果结果为 0,则返回 1。这意味着我们可以像 Java 或 C 程序员那些书写表达式,但 while 语句沿用的仍旧是 bash 那一套,视 0 为真。

实际上,这意味着我们可以编写一个无限循环:

while (( 1 )); do
    ...
done

对 C 程序员而言,这种写法“感觉是对的”。但要记住,while 语句查找的是为 0 的返回值,这里它确实可以得到,因为对于为真(也就是非 0)的结果,(( 1 )) 返回 0。

结束 while 循环的相关讨论之前,我们再来看看 while read 这个示例,它目前从标准输入(键盘)中读取输入信息,要想令其从文件中读取,该如何修改代码呢?

通常有 3 种实现方法。第一种完全不需要改动代码。只需要在调用脚本时将标准输入重定向到文件。

myscript < file.name

要是不想把这个工作留给调用脚本的用户呢?如果知道待处理的文件名,或者该文件要作为脚本的命令行参数,那就可以保持 while 循环不变,将其输入重定向到该文件。

while read lineoftext
do
    process that line
done < file.input

第三种方法是用 cat 命令将文件输出到标准输出,然后再将标准输出连接到 while 语句的标准输入。

cat file.input |
while read lineoftext
do
    process that line
done

因为管道的存在,cat 命令和 while 循环(包括其中的 process that line 部分)各自在单独的进程中运行。这意味着,如果你采用了这种方法,while 循环内部的命令不会影响到循环外部的其他部分。例如,在 while 循环中设置的变量在循环结束后也就失去了所设置的值。但如果你采用的是 while read ... done < file.input,就不会出现这种情况,因为这种方法并不涉及管道。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!