1. IF语句语法
if commands; then
commands
elif commands; then
commands
else
commands
if
1.1 退出状态
命令(包括脚本和Shell函数)在结束时会向系统返回一个值,称其为“退出状态”,这是一个取值范围在0-255的整数,代表命令执行成功还是失败。按照惯例,数值0表示成功,其他数值表示失败。Linux提供了一个可以用来检测退出状态的参数,如下示例:
[root@REAL01 ~]# ls -d /usr/bin
/usr/bin
[root@REAL01 ~]# echo $?
0
[root@REAL01 ~]# ls -ld /user/bin
ls: cannot access /user/bin: No such file or directory
[root@REAL01 ~]# echo $?
2
命令的手册页“Exit Status”一节中描述了命令会使用什么样的退出状态值。不过数值0总表示成功
Shell提供了两个及其简单的内建命令,除了返回退出状态值0或1,不做任何事。true命令总能执行成功,而false命令总执行失败。
[root@REAL01 ~]# true
[root@REAL01 ~]# echo $?
$?
[root@REAL01 ~]# false
[root@REAL01 ~]# echo $?
1
[root@REAL01 ~]#
如果if之后是命令列表,则判断其中最后一个命令的退出状态值。
[root@REAL01 ~]# if false; true; then echo "It is true."; fi
It is true.
[root@REAL01 ~]# if true; false; then echo "It is true."; fi
[root@REAL01 ~]#
1.2 test命令
test 命令用于检查某个条件是否成立,该命令有两种等价的形式,其中expression是一个表达式,求值结果要么为真,要么为假。如果为真,test命令的返回退出状态值为0;如果为假,则返回1。
第一种(了解即可)
test expression
第二种(推荐写法)
[ expression ]
注意的事,test和[其实都是命令。在Bash种,两者均为内建命令,表达式其实就是[命令的参数,该命令同时要求]作为其最后一个参数。
1.3 文件表达式
表达式 | 什么情况下为真 |
---|---|
file1 -nt file2 | file1比file2新 |
file1 -ot file2 | file1比file2旧 |
-b file | file存在且为快设备文件 |
-c file | file存在且为字符设备文件 |
-d file | file存在且为目录 |
-e file | file存在 |
-f file | file存在且为普通文件 |
-g file | file存在且设置了SGID位 |
-Gfile | file存在且为有效组ID所有 |
-k file | file存在且设置了“粘滞位” |
-L file | file存在且为符号链接 |
-O file | file存在且为有效用户ID所有 |
-r file | file存在且可读 |
-s file | file存在且不为空 |
-u file | file存在且设置了SUID位 |
-w file | file存在且可写 |
-x file | file存在且可执行 |
#!/bin/bash
#test-file
FILE=~/.bashrcs
if [ -e $FILE ]; then
if [ -f "$FILE" ]; then
echo "$FILE is a regular file."
fi
if [ -d "$FILE" ]; then
echo "$FILE is a directory."
fi
if [ -r "$FILE" ]; then
echo "$FILE is a readable file."
fi
if [ -w "$FILE" ]; then
echo "$FILE is a writable file."
fi
if [ -x "$FILE" ]; then
echo "$FILE is a excuteable file."
fi
else
echo "$FILE is not exist."
exit 1
fi
注意表达式中引用参数$FILE,尽管语法层面上并不要求添加引号,但引号可以防范参数为空或只包含空白字符的情况。如果 $FILE经过参数扩展后产生一个空值,就会导致错误(操作符会被解释为非空字符串,不再被视为操作符)。
1.4 字符串表达式
表达式 | 什么情况下为真 |
---|---|
string | string不为空 |
-n string | string的长度大于0 |
-z string | string的长度为0 |
string1 = string2 | string1和string2相同 |
string1 != string2 | string1和string2不相同 |
string1 > string2 | string1的排序位于string2之后 |
string1 < string2 | string1的排序位于string2之前 |
在使用><操作符时,必须引用起来(或者通过反斜线转义)。如果不这么做,两者会被Shell解释为重定向操作符,有可能造成破坏性后果。
#/bin/bash
#test-sting
ANSWER=maybe
if [ -z "ANSWER" ]; then
echo "There is no answer." >&2
fi
if [ "$ANSWER" = "yes" ]; then
echo "the answer is yes"
elif [ "$ANSWER" = "no" ]; then
echo "the answer is no"
elif [ "$ANSWER" = "maybe" ]; then
echo "the answer is maybe"
else
echo "the answer is UNKNOW"
fi
echo命令使用了重定向,将错误消息“There is no answer.”重定向到标准错误,这是处理错误消息的正确方式。
1.5 整数表达式
表达式 | 什么情况下为真 |
---|---|
string | string不为空 |
integer1 eq integer2 | integer1等于integer2 |
integer1 ne integer2 | integer1不等于integer2 |
integer1 -le integer2 | integer1小于或等于integer2 |
integer1 -lt integer2 | integer1小于integer2 |
integer1 -ge integer2 | integer1大于或等于integer2 |
integer1 -gt integer2 | integer1大于integer2 |
#!/bin/bash
#test-int
INT=-5
if [ -z "$INT" ]; then
echo "INT is empty." >&2
exit1
fi
if [ "$INT" -eq 0 ]; then
echo "INT is zero."
else
if [ "$INT" -lt 0 ]; then
echo "INT is negative."
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd."
fi
fi
1.6 test增强版
Bash提供了test增强版的复合命令[[. ]]支持所有test表达式,用法如下
[[.expression ]]
额外加入了一个重要的全新的字符串表达式。
string1 =~ regex
如果string1匹配ERE regex,则返回真。这就为数据验证这类任务提供了诸多可能性。在整数表达式士例终,如果常量INT含有整数以外的其他值,脚本就会执行失败。脚本需要一种方法来核实常量包含的是整数,可以使用上述表达式,按照下列方式改进脚本。
#!/bin/bash
#test-int2
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [ "$INT" -eq 0 ]; then
echo "INT is zero"
else
if [ "$INT" -lt 0 ]; then
echo "INT is negative"
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd"
fi
fi
else
echo "INT is not an integer." >&2
exit 1
fi
[[ ]]的另一个特性是其中的==操作符支持和路径名扩展一样的模式匹配。这使[[. ]]在评估文件和路径名的时候得以发挥作用。
[root@REAL01 test]# FILE=foo.bar
[root@REAL01 test]# if [[ $FILE == foo.* ]]; then
> echo "$FILE matches pattern 'foo.*'"
> fi
foo.bar matches pattern 'foo.*'
[root@REAL01 test]#
1.7 (())—为整数设计
除了符合命令[[ ]],Bash支持另一种复合命令(()),它在整数操作时用得上。该命令支持所有的算术求值。(())可用于执行算术真值测试。如果算术求值的结果不为0,则测试结果为真。上述脚本可以简化为:
#!/bin/bash
#test-int2
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if (($INT == 0)); then
echo "INT is zero"
else
if ((INT < 0)); then
echo "INT is negative"
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd"
fi
fi
else
echo "INT is not an integer." >&2
exit 1
fi
注意,这里使用了<和>,==则用于测试相等性。这种语法在处理整数时看起来更自然。除此之外,由于(())复合命令是Shell语法的一部分,并且只能处理整数,因此它能够通过名称来识别变量,不需要执行扩展操作。
1.8 组合表达式
可以将多个表达式组合在一起,形成更为复杂的测试。表达式是通过逻辑操作符组合起来的,可用的逻辑操作符有3种,分别是AND、OR、NOT。test和[[]]使用不同的操作符来表示逻辑操作。
操作 | test | [[]]和(()) |
---|---|---|
AND | -a | && |
OR | -o | || |
NOT | ! | ! |
- 用[[ ]]举例
#!/bin/bash
#test-int3
MIN_VAL=1
MAX_VAL=100
INT=50
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [[ "$INT" -gt "$MIN_VAL" && "$INT" -lt "$MAX_VAL" ]]; then
echo "INT is in range."
else
echo "INT is outside"
fi
else
echo "INT is not int." >&2
exit 1
fi
- 使用[ ]来改写一下
#!/bin/bash
#test-int3
MIN_VAL=1
MAX_VAL=100
INT=50
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [ "$INT" -gt "$MIN_VAL" -a "$INT" -lt "$MAX_VAL" ]; then
echo "INT is in range."
else
echo "INT is outside"
fi
else
echo "INT is not int." >&2
exit 1
fi
- 使用!非来改写[[ ]]
#!/bin/bash
#test-int3
MIN_VAL=1
MAX_VAL=100
INT=50
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [[ ! ("$INT" -gt "$MIN_VAL" && "$INT" -lt "$MAX_VAL") ]]; then
echo "INT is outside."
else
echo "INT is in range"
fi
else
echo "INT is not int." >&2
exit 1
fi
- 使用!非来改写[ ]
#!/bin/bash
#test-int3
MIN_VAL=1
MAX_VAL=100
INT=50
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [ ! \( "$INT" -gt "$MIN_VAL" -a "$INT" -lt "$MAX_VAL" \) ]; then
echo "INT is outside."
else
echo "INT is in range"
fi
else
echo "INT is not int." >&2
exit 1
fi
因为test使用的所有表达式和操作符均被Shell视为命令参数,所以那些对Bash具有特殊含义的字符(如<、>、(、))必须进行引用或转义。
1.9 控制操作符
对于&&操作符,先执行command1,仅当command1执行成功时,才执行command2.对于||操作符,先执行command1,仅当command1执行失败时,才执行command2.