if-then的测试功能
文章目录
退出状态码
定义
shell中运行的每个命令都使用退出状态码(exit status)告诉shell它已经运行完毕。退出状态 码是一个0~255的整数值,在命令结束运行时由命令传给shell。可以捕获这个值并在脚本中使用。
Linux提供了一个专门的变量$?来保存上个已执行命令的退出状态码。对于需要进行检查的 命令,必须在其运行完毕后立刻查看或使用$?变量。它的值会变成由shell所执行的最后一条命令的退出状态码。
按照惯例,一个成功结束的命令的退出状态码是0。如果一个命令结束时有错误,退出状态码就是一个正数值。
无效命令会返回一个退出状态码127。
exit命令
默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。你可以改变这种默认行为,返回自己的退出状态码。exit命令允许你在脚本结束时指定一个退出状态码。
$ cat test13
#!/bin/bash
# testing the exit status
var1=10
var2=30
var3=$[$var1 + $var2]
echo The answer is $var3
exit 5
$
当查看脚本的退出码时,你会得到作为参数传给exit命令的值。
$ chmod u+x test13
$ ./test13
The answer is 40
$ echo $?
5
$
也可以在exit命令的参数中使用变量。
exit $var3
因为退出状态码最大只能是255,退出状态码被缩减到了0~255的区间。shell通过模运算得到这个结果.最终的结果是指定的数值除以256后得到的余数。
例如指定的值是300(返回值),余数是44,因此这个余数就成了最后的状态退出码。
if-then基本结构
基本结构如下:
if command
then
commands
fi
bash shell的if语句会运行if后面的那个命令。如果该命令的退出状态码(参见第11章)是0 (该命令成功运行),位于then部分的命令就会被执行。如果该命令的退出状态码是其他值,then部分的命令就不会被执行,bash shell会继续执行脚本中的下一个命令。fi语句用来表示if-then 语句到此结束。
在if-then语句中,不管命令是否成功执行,你都只有一种选择。如果命令返回一个非零退 出状态码,bash shell会继续执行脚本中的下一条命令。在这种情况下,如果能够执行另一组命令 2 就好了。这正是if-then-else语句的作用。 if-then-else语句在语句中提供了另外一组命令。
if command then
commands
else
commands
fi
有时你需要检查脚本代码中的多种条件。对此,可以使用嵌套的if-then语句.在脚本中使用这种嵌套if-then语句的问题在于代码不易阅读,很难理清逻辑流程。
可以使用else部分的另一种形式:elif。这样就不用再书写多个if-then语句了。elif使 用另一个if-then语句延续else部分。
if command1
then
commands
elif command2
then
more commands
fi
你会经常发现自己在尝试计算一个变量的值,在一组可能的值中寻找特定值。在这种情形下,你不得不写出很长的if-then-else语句,
有了case命令,就不需要再写出所有的elif语句来不停地检查同一个变量的值了。case命令会采用列表格式来检查单个变量的多个值。
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac
case命令会将指定的变量与不同模式进行比较。如果变量和模式是匹配的,那么shell会执行 为该模式指定的命令。可以通过竖线操作符在一行中分隔出多个模式模式。星号会捕获所有与已知模式不匹配的值。这里有个将if-then-else程序转换成用case命令的例子。
|
|
case命令提供了一个更清晰的方法来为变量每个可能的值指定不同的选项。
test命令
test命令提供了在if-then语句中测试不同条件的途径。如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0。
这样if-then语句就与其他编程语言中的if-then语句 以类似的方式工作了。如果条件不成立,test命令就会退出并返回非零的退出状态码,这使得 if-then语句不会再被执行。
test命令的格式非常简单。
test condition
condition是test命令要测试的一系列参数和值。当用在if-then语句中时,test命令看起来是这样的。
if test condition then
commands
fi
如果不写test命令的condition部分,它会以非零的退出状态码退出,并执行else语句块。
bash shell提供了另一种条件测试方法,无需在if-then语句中声明test命令。
if [ condition ] then
commands
fi
方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错。
test命令可以判断三类条件:
- 数值比较
- 字符串比较
- 文件比较
数值比较
使用test命令最常见的情形是对两个数值进行比较。
数值条件测试可以用在数字和变量上。
注意bash shell只能处理整数。如果使用浮点值进行test比较,将会报错.
字符串比较
条件测试还允许比较字符串值。比较字符串比较烦琐.
当要开始使用测试条件的大于或小于功能时,就会出现两个经常困扰shell程序员的问题:
-
大于号和小于号必须转义,否则shell会把它们当作重定向符号,把字符串值当作文件名;
-
大于和小于顺序和sort命令所采用的不同
在编写脚本时,第一条可能会导致一个不易察觉的严重问题。
val1=baseball
val2=hockey
if [ $val1 > $val2 ]
这个脚本中只用了大于号,没有出现错误,但结果是错的。脚本把大于号解释成了输出重定向.因此,它创建了一个名为hockey的文件。由于重定向的顺利完成,test命令 返回了退出状态码0,if语句便以为所有命令都成功结束了。
要解决这个问题,就需要正确转义大于号。
if [ $val1 \> $val2 ]
第二个问题更细微,除非你经常处理大小写字母,否则几乎遇不到。sort命令处理大写字母的方法刚好跟test命令相反。
在比较测试中,大写字母被认为是小于小写字母的。但sort命令恰好相反。当你将同样的 字符串放进文件中并用sort命令排序时,小写字母会先出现。这是由各个命令使用的排序技术不同造成的。
比较测试中使用的是标准的ASCII顺序,根据每个字符的ASCII数值来决定排序结果。sort 命令使用的是系统的本地化语言设置中定义的排序顺序。对于英语,本地化设置指定了在排序顺 序中小写字母出现在大写字母前。
-n和-z可以检查一个变量是否含有数据。
文件比较
最后一类比较测试很有可能是shell编程中最为强大、也是用得最多的比较形式。它允许你测 试Linux文件系统上文件和目录的状态。
-d测试会检查指定的目录是否存在于系统中。如果你打算将文件写入目录或是准备切换到某 个目录中,先进行测试总是件好事情。
if [ -d $jump_directory ]
-e比较允许你的脚本代码在使用文件或目录前先检查它们是否存在。
-e比较可用于文件和目录。要确定指定对象为文件,必须用-f比较。
在尝试从文件中读取数据之前,最好先测试一下文件是否可读。可以使用-r比较测试。
应该用-s比较来检查文件是否为空,尤其是在不想删除非空文件的时候。要留心的是,当 -s比较成功时,说明文件中有数据。
-w比较会判断你对文件是否有可写权限。
-x比较是判断特定文件是否有执行权限的一个简单方法。
-O比较可以测试出你是否是文件的属主。
-G比较会检查文件的默认组,如果它匹配了用户的默认组,则测试成功。由于-G比较只会 检查默认组而非用户所属的所有组,这会叫人有点困惑。
-nt比较会判定一个文件是否比另一个文件新。如果文件较新,那意味着它的文件创建日 期更近。-ot比较会判定一个文件是否比另一个文件旧。如果文件较旧,意味着它的创建日期更早。
复合条件测试
if-then语句允许你使用布尔逻辑来组合测试。有两种布尔运算符可用:
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
第一种布尔运算使用AND布尔运算符来组合两个条件。要让then部分的命令执行,两个条件都必须满足。
if-then的高级特性
bash shell提供了两项可在if-then语句中使用的高级特性:
- 用于数学表达式的双括号
- 用于高级字符串处理功能的双方括号
双括号
双括号命令允许你在比较过程中使用高级数学表达式。test命令只能在比较中使用简单的 算术操作。双括号命令提供了更多的数学符号.双括号命令的格式如下:
(( expression ))
expression可以是任意的数学赋值或比较表达式。
可以在if语句中用双括号命令,也可以在脚本中的普通命令里使用来赋值。
if (( $val1 ** 2 > 90 )) then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi
注意,不需要将双括号中表达式里的大于号转义。
使用双方括号
双方括号命令提供了针对字符串比较的高级特性。双方括号命令的格式如下:
[[ expression ]]
双方括号里的expression使用了test命令中采用的标准字符串比较。但它提供了test命令未提供的另一个特性——模式匹配(pattern matching)。
在模式匹配中,可以定义一个正则表达式(将在第20章中详细讨论)来匹配字符串值。
|
|
使用了双等号(==)。双等号将右边的字符串(r*)视为一个模式, 并应用模式匹配规则。双方括号命令$USER环境变量进行匹配,看它是否以字母r开头。如果是的话,比较通过,shell会执行then部分的命令。
文章作者 Forz
上次更新 2017-08-09