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

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

成于坚持,败于止步

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

条件判断结构如下:

if [ condition-true]
then
	command1
	command2
	.......
else
	command3
	command4
	.......
if

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

if [ -x "$filename" ]; then

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

if [condition1]
then
	command1
	......
elif[condition2]
then
	command2
	.......
else
	command3
	.....
fi

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

#!/bin/bash

#  小技巧:
#  如果你不能够确定一个特定的条件该如何进行判断,那么就使用if-test结构. 
echo "Testing \"0\""
if [ 0 ]      # zero
then
	echo "0 is true."
else
	echo "0 is false."
fi            # 0 为真.

echo
echo "Testing \"1\""
if [ 1 ]      # one
then
	echo "1 is true."
else
	echo "1 is false."
fi            # 1 为真.

echo
echo "Testing \"-1\""
if [ -1 ]     # 负1
then
	echo "-1 is true."
else
	echo "-1 is false."
fi            # -1 为真.

echo
echo "Testing \"NULL\""
if [ ]        # NULL (空状态)
then
	echo "NULL is true."
else
	echo "NULL is false."
fi            # NULL 为假.

echo
echo "Testing \"xyz\""
if [ xyz ]    # 字符串
then
	echo "Random string is true."
else
	echo "Random string is false."
fi            # 随便的一串字符为真.

echo
echo "Testing \"\$xyz\""
if [ $xyz ]   # 判断$xyz是否为null, 但是这只是一个未初始化的变量.
then
	echo "Uninitialized variable is true."
else
	echo "Uninitialized variable is false."
fi            # 未定义的初始化为假.

echo
echo "Testing \"-n \$xyz\""
if [ -n "$xyz" ]            # 更加正规的条件检查.
then
	echo "Uninitialized variable is true."
else
	echo "Uninitialized variable is false."
fi            # 未初始化的变量为假.

echo
xyz=          # 初始化了, 但是赋null值.
echo "Testing \"-n \$xyz\""
if [ -n "$xyz" ]
then
	echo "Null variable is true."
else
	echo "Null variable is false."
fi            # null变量为假. 

echo
xyz=1         # 初始化了, 但是赋null值.
echo "Testing \"-n \$xyz initilized\""
if [ -n "$xyz" ]
then
	echo "Initilize variable is true."
else
	echo "Null variable is false."
fi  

echo
echo "Testing \"false\""
if [ "false" ]              #  看起来"false"只不过是一个字符串而已. 
then
	echo "\"false\" is true." #+ 并且条件判断的结果为真.
else
	echo "\"false\" is false."
fi            # "false" 为真.

echo
echo "Testing \"\$false\""  # 再来一个, 未初始化的变量.
if [ "$false" ]
then
	echo "\"\$false\" is true."
else
	echo "\"\$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/bash

one=
if test -z "$one"
then
	echo "No command-line arguments."
else
	echo "First command-line argument is $one."
fi
one=1
if test -z "$one"
then
	echo "No command-line arguments."
else
	echo "First command-line argument is $one."
fi

two=
echo
if /usr/bin/test -z "$two"      # 与内建的"test"命令结果相同. 
then
	echo "No command-line arguments."
else
	echo "First command-line argument is $two."
fi
two=2
if /usr/bin/test -z "$two"      # 与内建的"test"命令结果相同. 
then
	echo "No command-line arguments."
else
	echo "First command-line argument is $two."
fi

echo
three=
if [ -z "$three" ]
then
	echo "No command-line arguments."
else
	echo "First command-line argument is $three."
fi
three=3
if [ -z "$three" ]
then
	echo "No command-line arguments."
else
	echo "First command-line argument is $three."
fi
 
echo
four=
if /usr/bin/[ -z "$four" ]
then
	echo "No command-line arguments."
else
	echo "First command-line argument is $four."
fi
four=4
if /usr/bin/[ -z "$four" ]
then
	echo "No command-line arguments."
else
	echo "First command-line argument is $four."
fi

echo
exit 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/bash
echo "For [[ ]] test:"
file=/etc/passwd
if [[ -e $file ]]
then
	echo "$file exits"
else
	echo "$file not exits"
fi
exit 0
结果:

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

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

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

#!/bin/bash
dir=/dev/pass
if cd "$dir"
then
	echo "Now you are in $dir"
else
	echo "You can't change to $dir"
fi

dir=/dev/char
if cd "$dir"
then
	echo "Now you are in $dir"
else
	echo "You can't change to $dir"
fi

dir=/dev/pass
if cd "$dir" 2> /dev/null
then
	echo "Now you are in $dir"
else
	echo "You can't change to $dir"
fi
exit 0
结果:

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

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

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

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

#!/bin/bash
var1=10
var2=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 ))                                      # 0
echo "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 $?."     # 1
exit 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

待续。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值