The for Command
1 | for var in word1 word2 |
shell 会进行文件替换。
1 | for f in * |
The $@
Variable
1 | args |
1 | ./args a b c |
shell 使用 $1 $2 ...
替换 $*
,而使用 $@
时,shell 会使用 "$1" "$2" ...
替换。不同之处就是双引号。
1 | echo Number of args passed is $# |
The for without the list
1 | for arg |
如果省略 in list
,那么 shell 会命令行的参数替换到这里,类似 for arg in "$@"
。
The while
Command
1 | while commandt |
1 | i=1 |
while
循环一般和 shift
配合使用来处理未知数量的命令行参数。
1 | while [ "$#" -ne 0 ] |
The until
Command
while
命令是当判断为真是继续执行,而 until
则相反,如果条件为假则执行,为真不执行。
1 | until [ command ] |
默认情况下,当 log off
系统时,你启动的程序都会退出,如果想要程序继续执行则可以使用 nohup
。
More on loops
Breaking Out of a Loop
break
退出循环,break n
,退出最近的 n 次循环。
Skipping the Remaining Commands in a Loop
continue
continue n
。
Executing a Loop in the Background
可以使用 &
符号把整个循环放到后台执行。
1 | for file in * |
shell 把循环当作命令处理,所以可以在结构结束时(done、fi、esac)执行重定向、后台执行甚至使用管道。
I/O Redirection on a Loop
可以在循环上执行重定向操作,作用于循环体的输入重定向会应用到循环体中的所有命令,输出重定向也是如此,block redirection
。
1 | for i in 1 2 3 4 |
单个语句可以覆盖块重定向(block redirection),就像 shell 程序中的任何其他语句可以显式从指定源读取或将输出发送到指定目标一样。
要强制输入或输出来自或去往终端,使用 /dev/tty
,它始终指你的终端程序,无论使用的是 Mac、Linux 还是 Unix 系统。
1 | for file |
同样可以重定向循环的标准错误输出,在 done
后直接输入 2> file
。
1 | while [ "$endofdata" -ne TRUE ] |
循环体中所有命令的标准错误输出都被重定向到 errors
文件。
2>
格式的一种变体通常用于确保错误消息到达终端,即使脚本可能将其输出重定向到文件或管道:
echo "Error: no file" 1>&2
,默认情况下,echo
将其输出发送到标准输出(文件描述符 1),而文件描述符 2 保留标准错误,默认情况下不会在文件重定向或管道上重定向。因此,上面的符号意味着来自 echo
的错误消息应该将其 file #1
输出重定向到file #2
,即标准错误。
1 | for i in "once" |
即使整个循环体的标准输出都重定向了,里面的单个命令可以覆盖这种行为,第二个命令,把标准输出重定向到标准错误了。或者这样理解,标准输出被重定向了,但是第二个命令又把标准输出重定向到标准错误了。
Piping Data into and out of a Loop
一个命令的输出可以使用管道传递给一个循环体,而一个循环体的输出也可以通过管道传递给别的命令。
1 | for i in 1 2 3 4 |
Typing a Loop on One Line
1 | for i in 1 2 3 4 |
可以改写为一行 for i in 1 2 3 4; do echo $i; done
。
1 | if [condition]; then |
推荐这种形式写 shell。
The getopts
Command
给 shell 脚本添加 options
,当开始写这种程序时,会发现非常会变得特别复杂。
但是 shell 提供了内置的叫做 getopts
的命令,让命令行参数变得更加容易。
getopts options variable
,options
是一些字符,比如 ab:c
,意味着 -a
和 -c
是合法的选项,而 -b
则需要一个参数。
然而,getopts
命令被设计为在循环内执行,因为它可以轻松地执行每个用户指定选项所需的任何操作。每次循环时,getopts
都会检查下一个命令行参数,并通过检查该参数是否以减号开头并后跟指定为选项的任何字母来确定它是否是有效选项。如果是,getopts
将匹配的选项字母存储在指定变量内并返回零退出状态。
如果减号后面的字母未在选项中列出,则 getopts
在以零退出状态返回之前会在变量内存储一个问号。它还将有关用户指定的错误参数的错误消息写入标准错误。
如果命令行上没有留下更多参数,或者当前参数不以减号开头,则 getopts
返回非零退出状态,允许脚本处理任何后续参数。
例子
比如,想写一个脚本让它能识别 -a
-i
-r
选项,那么命令就像这样 getopts "air" option
,这里第一个参数 air
指定了三个可接收的命令行标志(command flags) -a -i -r
,option
是 getopts
将用来存储遇到的每个匹配值的变量的名称。
group/clustered options
foo -a -i -r
== foo -air
。
通过 :
告诉 getopts
某个选项需要参数。如果 getopts
在需要参数的选项后找不到参数,它会在变量中存储一个问号,并向标准错误输出一条错误消息。否则,它将变量中的字符和用户指定的参数存储在名为 OPTARG
的特殊变量中。
关于 getopts
的最后一点:另一个称为 OPTIND
的特殊变量最初设置为 1,并且每次 getopts
返回时都会更新以反映要处理的下一个命令行参数的编号。
1 |
|