条件语句
1 | if commandt |
0表示成功
Exit Status
要了解条件测试如何工作,了解 Unix 如何处理所谓的退出状态非常重要,无论什么时候任何程序执行完毕都会向 shell 返回 exit status code。这个退出码是一个数字来指代程序是否成功运行。通常 0 表示成功,非 0 表示失败。
程序失败的原因有很多,通常使用不同的非 0 状态表示不同类型的错误。
在一个管道中,退出码通常是最后一个命令产生的,who | grep fred
,shell 使用 grep 的返回值来表示整个管道的退出码。
$?
shell 变量 $?
由 shell 自动设置为最后执行的命令的退出状态。
echo $?
发生错误时的返回值在不同版本的 Unix 中可能不同,但是执行成功的返回值总是 0。
1 | on |
判断条件语句的返回值是否为 0,如果是则表示成功执行对应的 then
语句。如果返回值为非 0,则 echo
不会执行。
echo
命令使用缩进只是为了代码的可读性。
执行程序后会发现几个问题,当返回值为 0 时,who | grep $user
的结果会打印出来。可以重定向到 /dev/null
。
仅仅使用 grep $user
是不够的,会匹配到其他用户。
1 | on |
test
test expression
,test
会评估 expression
的结果,如果结果是 true,那么 test
返回 0,否则返回非 0。
String Operators
test "$name" = abc
,注意 test
必须能看到所有的 operands
($name 和 abc)和 operators
作为单独的参数,这就意味着需要用空白字符分隔。
Operator | return TRUE(exit status of 0) if |
---|---|
string1 = string2 | 两个字符串相等 |
string1 != string2 | 两个字符串不相等 |
string | string is not null |
-n string | string is not null (string must be seen by test) |
-z string | string is null (string must be seen by test) |
1 | blanks=" " |
第一个例子中,shell 会去掉多余的空格,就像 echo one two
一样,第二个例子中则会包含空格。
关于空白字符和引号是 shell 编程中最容易产生错误的地方。
可以任务 -n
和 -z
是对字符串长度的判断。
1 | echo $symbol |
An Alternative Format for test
test expression
等价于 [ expression ]
,注意空格要保留,推荐使用这种语法。
Integer Operator
-eq -ge -gt -le -lt -ne
,[ "$count" -eq 0 ]
。
值得注意的是当使用整数操作符时,是 test
命令复杂把变量解析为整数的,而不是 shell。
1 | x1="005" |
File Operators
Operator | return TRUE(exit status of 0) if |
---|---|
-d file |
file is a directory |
-e file |
file exists |
-f file |
file is an ordinary file |
-r file |
file is readable by the process |
-s file |
file has nonzero length |
-w file |
file is writeable by the process |
-x file |
file is executable |
-L file |
file is a symbolic link |
The Logical Negation Operator
[ ! -r /home/smith/phonebook ]
, [ ! "$x1" = "$x2" ]
和 [ $"x1" != "$x2" ]
效果一样。
The Logical AND Operator -a
[ -f "$mailfile" -a -r "$mailfile" ]
。
[ "$count" -ge 0 -a "$count" -lt 10 ]
-a
优先级比整数比较操作符低。
短路,只要遇到一个返回值是 false,接下来的判断就不会执行。
[ ! -f "$file" -a $(who > $file) ]
,如果前面的判断是 false,后面的就不会执行。
Parentheses
可以使用括号明确指定执行顺序。[ \( "$count" -ge 0 \) -a \( "$count" -lt 10 \) ]
。
The Logical OR Operator -o
[ -n "$mailopt" -o -r $HOME/mailfile ]
,-o
的优先级比 -a
低。
"$a" -eq 0 -o "$b" -eq 2 -a "$c" -eq 10
等价于 "$a" -eq 0 -o ("$b" -eq 2 -a "$c" -eq 10)
。
The else
1 | on |
要把原型转换成能够长期使用的程序,需要确保正确的参数数量传递。
1 | on |
The exit Command
built in command exit
能让程序立刻退出。exit n
,如果 n 未提供,那么返回最后一次执行的命令的返回值,相当于 exit $?
。
如果在命令行直接执行则会退出相应的 shell。
1 | rem |
The elif Construct
1 | greetings |
1 | greetings |
一个重要的改善,程序更易读了。
一般不使用 date | cut -c12-13
,而是 date +%H
。
rem 改进
1 | rem |
The case command
1 | case v in |
pattern 可以是正则表达式。
1 | ctype |
bug?
The -x Option for Debugging Programs
sh -x ctype a
,发现 echo "$char" | wc -c
结果是2,包含了换行符号。要修改条件为 [ "$numchars" -ne 2 ]
。
new version avoid use wc
。
1 | if [ $# -ne 1 ] |
1 | greetings |
The Null Command
空命令,类似于 python 中的 pass。
The && and || Constructs
shell 有两个特殊的结构,能够根据前面的命令是成功还是失败来执行命令。是 if 语句的简写形式。
commad1 && command2
,第一个命令返回 0 才执行第二个命令,如果是非 0,那么忽略第二个命令。
commad1 || command2
,第一个命令返回非 0 才执行第二个命令,如果是 0,那么忽略第二个命令。