Shell流程控制之IF语句

发布于:2022-11-13 ⋅ 阅读:(597) ⋅ 点赞:(0)

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 ! !
  1. 用[[ ]]举例
#!/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
  1. 使用[ ]来改写一下
#!/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
  1. 使用!非来改写[[ ]]
#!/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
  1. 使用!非来改写[ ]
#!/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.


网站公告

今日签到

点亮在社区的每一天
去签到