shell脚本学习指南[二](Arnold Robbins & Nelson H.F. Beebe著)

2019-09-23 09:42:16于海丽

126 命令找到了,但文件无法执行。
127 命令找不到。
>128 命令因收到信号而死亡。

令人好奇的是,POSIX留下退出状态128未定义,仅要求它表示某种失败。因为只有低位的8个位会返回给父进程,所以大于255的退出状态都会替换成该值除以256之后的余数。返回值命令:exit value_number 。

关于判断语句 if-then-elif-else-fi 语句给个语法不再赘述:


if pipeline
[ pipeline ... ]
then
statements-if-true-1
[ elif pipeline
[ pipeline ... ]
then
statements-if-true-2 ... ]
[ else
statements-if-all-else-fails ]
fi

if判断力你可以使用 !、&&、|| 等C语言里的这些逻辑判断符号。
这里介绍一个test命令,它为了测试shell脚本里的条件,通过退出状态返回其结果,它有第二种形式即 [...] ,单要注意的是方括号根据字面意义逐字地输入,且必须与括号起来的expression以空白隔开。如:test "$str1" = "$str2" 等同于 [ "$str1" = "$str2" ] 。test有好多参数啊,好多。。。自己man吧(敢不敢把26个字母都用完?!!! TT)。这里给出之前的finduser脚本的改良版:


#! /bin/sh
#finduser --- 寻找是否有第一个参数指定的用户
if [ $# -ne 1 ]
then
echo Usage: finduser username >&2
exit 1
fi
who | grep $1

关于case语句,给出例子不再赘述,都十分雷同C语言的。


case $1 in #测试$1
-f )
.... #针对-f选项的程序代码
;; ##类似break
-d | --directory ) #支持长选项
...

* ) #上边都不匹配的默认选项,非必须
echo $1:unknow option >&2
exit 1
;; #也非必须
esac

关于for循环,给出一个实例:


for i in atlbrochure*.xml
do
echo $i
mv $i $i.old
sed 's/Athlanta/&, the capital of the South/' < $i.old >$i
done

这个循环将每个原始文件备份为副文件名为.old的文件,之后再使用sed处理文件建立新文件。同时有输出文件名,作为进度的一种提示。另外for循环里的in列表(list)是可选的,如果省略则遍历整个命令行参数,就好像输入了 for i in "$@" 。

while和until循环也都类似,语法为:

while condition
do
statements
done

until condition
do
statements
done

两者不同之处在于如何对待condition的退出状态,只要condition成功,while就继续循环。只要condition不成功,until则一直循环。
在以上循环里,你仍然可以使用break和continue,功能同C语言一样。

shift之前提到过,它还可以接受一个可选参数,也就是要移动几位。

针对参数的处理有一个getopts命令简化了选项处理,它能理解POSIX选项中将多个选项字母组织到一起的用法,也可以用来遍历整个命令行参数,一次一个参数。该命令会自动过滤掉参数里的-,--等符号。如果得到不合法选项字母,该命令会返回一个?符号。