高级Bash脚本编程指南(6):条件测试结构

来源:互联网 发布:笑郭网络验证破解 编辑:程序博客网 时间:2024/05/24 23:13
高级Bash脚本编程指南(6):条件测试结构

成于坚持,败于止步

if/then结构用来判断命令列表的退出状态码是否为0(因为在UNIX惯例, 0表示"成功"), 如果成功的话, 那么就执行接下来的一个或多个命令,有一个专有命令[ (左中括号, 特殊字符). 这个命令与test命令等价, 并且出于效率上的考虑, 这是一个内建命令. 这个命令把它的参数作为比较表达式或者作为文件测试, 并且根据比较的结果来返回一个退出状态码(0 表示真, 1表示假)

条件判断结构如下:

if [ condition-true]thencommand1command2.......elsecommand3command4.......if

如果if和then在条件判断的同一行上的话, 必须使用分号来结束if表达式. if和then都是关键字. 关键字(或者命令)如果作为表达式的开头, 并且如果想在同一行上再写一个新的表达式的话, 那么必须使用分号来结束上一句表达式.

if [ -x "$filename" ]; then

不过同样要注意else if的出现,结构如下

if [condition1]thencommand1......elif[condition2]thencommand2.......elsecommand3.....fi

不过跟我们熟悉的c语言中的判断还是很多不一样,我们看看一个测试条件真假的简单测试程序:

#!/bin/bash#  小技巧:#  如果你不能够确定一个特定的条件该如何进行判断,那么就使用if-test结构. echo "Testing \"0\""if [ 0 ]      # zerothenecho "0 is true."elseecho "0 is false."fi            # 0 为真.echoecho "Testing \"1\""if [ 1 ]      # onethenecho "1 is true."elseecho "1 is false."fi            # 1 为真.echoecho "Testing \"-1\""if [ -1 ]     # 负1thenecho "-1 is true."elseecho "-1 is false."fi            # -1 为真.echoecho "Testing \"NULL\""if [ ]        # NULL (空状态)thenecho "NULL is true."elseecho "NULL is false."fi            # NULL 为假.echoecho "Testing \"xyz\""if [ xyz ]    # 字符串thenecho "Random string is true."elseecho "Random string is false."fi            # 随便的一串字符为真.echoecho "Testing \"\$xyz\""if [ $xyz ]   # 判断$xyz是否为null, 但是这只是一个未初始化的变量.thenecho "Uninitialized variable is true."elseecho "Uninitialized variable is false."fi            # 未定义的初始化为假.echoecho "Testing \"-n \$xyz\""if [ -n "$xyz" ]            # 更加正规的条件检查.thenecho "Uninitialized variable is true."elseecho "Uninitialized variable is false."fi            # 未初始化的变量为假.echoxyz=          # 初始化了, 但是赋null值.echo "Testing \"-n \$xyz\""if [ -n "$xyz" ]thenecho "Null variable is true."elseecho "Null variable is false."fi            # null变量为假. echoxyz=1         # 初始化了, 但是赋null值.echo "Testing \"-n \$xyz initilized\""if [ -n "$xyz" ]thenecho "Initilize variable is true."elseecho "Null variable is false."fi  echoecho "Testing \"false\""if [ "false" ]              #  看起来"false"只不过是一个字符串而已. thenecho "\"false\" is true." #+ 并且条件判断的结果为真.elseecho "\"false\" is false."fi            # "false" 为真.echoecho "Testing \"\$false\""  # 再来一个, 未初始化的变量.if [ "$false" ]thenecho "\"\$false\" is true."elseecho "\"\$false\" is false."fi            # "$false" 为假.现在, 我们得到了预期的结果.exit 0
看看结果先:

root@ubuntu:~/resource/study/shell# ./ifelse-test Testing "0"0 is true.Testing "1"1 is true.Testing "-1"-1 is true.Testing "NULL"NULL is false.Testing "xyz"Random string is true.Testing "$xyz"Uninitialized variable is false.Testing "-n $xyz"Uninitialized variable is false.Testing "-n $xyz"Null variable is false.Testing "-n $xyz initilized"Initilize variable is true.Testing "false""false" is true.Testing "$false""$false" is false.
其实这个结果还是让人感觉挺意外的上面的0,1,-1全部为真,随意字符为真,未初始化变量为假,已初始化变量为真,null为假
test,/usr/bin/test,[ ],和/usr/bin/[ 这么多,看的我很晕,其实他们都是等价的

看一个实例验证一下:

#!/bin/bashone=if test -z "$one"thenecho "No command-line arguments."elseecho "First command-line argument is $one."fione=1if test -z "$one"thenecho "No command-line arguments."elseecho "First command-line argument is $one."fitwo=echoif /usr/bin/test -z "$two"      # 与内建的"test"命令结果相同. thenecho "No command-line arguments."elseecho "First command-line argument is $two."fitwo=2if /usr/bin/test -z "$two"      # 与内建的"test"命令结果相同. thenecho "No command-line arguments."elseecho "First command-line argument is $two."fiechothree=if [ -z "$three" ]thenecho "No command-line arguments."elseecho "First command-line argument is $three."fithree=3if [ -z "$three" ]thenecho "No command-line arguments."elseecho "First command-line argument is $three."fi echofour=if /usr/bin/[ -z "$four" ]thenecho "No command-line arguments."elseecho "First command-line argument is $four."fifour=4if /usr/bin/[ -z "$four" ]thenecho "No command-line arguments."elseecho "First command-line argument is $four."fiechoexit 0
看一看执行结果;

root@ubuntu:~/resource/study/shell# ./iftest No command-line arguments.First command-line argument is 1.No command-line arguments.First command-line argument is 2.No command-line arguments.First command-line argument is 3.No command-line arguments.First command-line argument is 4.
上面的验证说明他们是完全等价的,毫无疑问

[[ ]]结构和[ ]结构更加通用,在[[ ]]之间的所有字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换

#!/bin/bashecho "For [[ ]] test:"file=/etc/passwdif [[ -e $file ]]thenecho "$file exits"elseecho "$file not exits"fiexit 0
结果:

root@ubuntu:~/resource/study/shell# ./double For [[ ]] test:/etc/passwd exits
这里-e是用来测试指定文件是否存在的,在这里使用[ ]其实也是一样的

使用[[ ... ]]条件判断结构, 而不是[ ... ], 能够防止脚本中的许多逻辑错误. 比如, &&||<, 和> 操作符能够正常存在于[[ ]]条件判断结构中, 但是如果出现在[ ]结构中的话, 会报错 

if后面也不一定非得是test命令或者是用于条件判断的中括号结构( [ ] 或 [[ ]] )
看一个例子吧

#!/bin/bashdir=/dev/passif cd "$dir"thenecho "Now you are in $dir"elseecho "You can't change to $dir"fidir=/dev/charif cd "$dir"thenecho "Now you are in $dir"elseecho "You can't change to $dir"fidir=/dev/passif cd "$dir" 2> /dev/nullthenecho "Now you are in $dir"elseecho "You can't change to $dir"fiexit 0
结果:

root@ubuntu:~/resource/study/shell# ./test1 ./test1: line 3: cd: /dev/pass: No such file or directoryYou can't change to /dev/passNow you are in /dev/charYou can't change to /dev/pass

第一个因为没有指定的目录,所以会自动提示第一行的错误提示,同时if检查到返回状态时false,指定目录存在,没有任何疑问,针对第三个出来为什么没有输出信息,因为2>  /dev/null会隐藏错误信息

"if COMMAND"结构将会返回COMMAND的退出状态码.

与此相似, 在中括号中的条件判断也不一定非得要if不可, 也可以使用列表结构,列表结构到底是什么,一块通过实例来理解一下

#!/bin/bashvar1=10var2=20[ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2"dir=/dev/pass[ -d "$dir" ] || echo "$dir directory does not exist"exit 0
结果:

root@ubuntu:~/resource/study/shell# ./test2 10 is not equal to 20/dev/pass directory does not exist
这个实例中出现的&& 和 || 就是上面说的列表结构,&&表示前面的返回结果是true则执行后面的echo,|| 表示前面的返回结果是false则指行后面的echo
(( ))结构扩展并计算一个算术表达式的值. 如果表达式的结果为0, 那么返回的退出状态码为1, 或者是"假". 而一个非零值的表达式所返回的退出状态码将为0, 或者是"true". 这种情况和先前所讨论的test命令和[ ]结构的行为正好相反.
听起来感觉有点拗口,看实例吧

#!/bin/bash# 算术测试.# (( ... ))结构可以用来计算并测试算术表达式的结果. # 退出状态将会与[ ... ]结构完全相反!(( 0 ))echo "Exit status of \"(( 0 ))\" is $?."         # 1(( 1 ))echo "Exit status of \"(( 1 ))\" is $?."         # 0(( 5 > 4 ))                                      # 真echo "Exit status of \"(( 5 > 4 ))\" is $?."     # 0(( 5 > 9 ))                                      # 假echo "Exit status of \"(( 5 > 9 ))\" is $?."     # 1(( 5 - 5 ))                                      # 0echo "Exit status of \"(( 5 - 5 ))\" is $?."     # 1(( 5 / 4 ))                                      # 除法也可以.echo "Exit status of \"(( 5 / 4 ))\" is $?."     # 0(( 1 / 2 ))                                      # 除法的计算结果 < 1.echo "Exit status of \"(( 1 / 2 ))\" is $?."     # 截取之后的结果为 0.(( 1 / 0 )) 2>/dev/null                          # 除数为0, 非法计算. echo "Exit status of \"(( 1 / 0 ))\" is $?."     # 1exit 0
结果:
root@ubuntu:~/resource/study/shell# ./test3 Exit status of "(( 0 ))" is 1.Exit status of "(( 1 ))" is 0.Exit status of "(( 5 > 4 ))" is 0.Exit status of "(( 5 > 9 ))" is 1.Exit status of "(( 5 - 5 ))" is 1.Exit status of "(( 5 / 4 ))" is 0.Exit status of "(( 1 / 2 ))" is 1.Exit status of "(( 1 / 0 ))" is 1.
上面实例中$? 获取到上面最后一天指令的返回状态,我们看到了跟我们之前看到的结果是相符的,如果表达式的结果为0, 那么返回的退出状态码为1, 或者是"假". 而一个非零值的表达式所返回的退出状态码将为0, 或者是"true". 这种情况和先前所讨论的test命令和[ ]结构的行为正好相反,所以第一条返回状态时1,怎if条件就是false

先到这里了,O(∩_∩)O~

我的专栏地址:http://blog.csdn.net/column/details/shell-daily-study.html

待续。。。

原创粉丝点击