利用 test 命令提高您的脚本编制水平

发表于:2007-8-28 14:37

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:T.Sing    来源:T.Sing'Blog

  以下示例显示了一个代码段,其中在命令行中给出的值必须等于 7:

#example5if [ $1 -eq 7 ]thenecho "You've entered the magic number."else echo "You've entered the wrong number."fi

  运行中:

$ example5 6You've entered the wrong number.$$ example5 7You've entered the magic number.$

  和字符串一样,比较的值可以是在脚本外为变量赋的值,而不必总是在命令行中提供。以下示例演示了实现这一点的一种方法:

#example6if [ $1 -gt $number ]thenecho "Sorry, but $1 is too high."else echo "$1 will work."fi$ set number=7$ export number$ example6 8Sorry, but 8 is too high.$ example6 77 will work.$

  整数比较运算符最佳的用途之一是评估指定的命令行变量的数目,并判断它是否符合所要求的标准。例如,如果某个特定的命令只能在有三个或更少变量的情况下运行,

#example7 - display variables, up to threeif [ "$#" -gt 3 ]thenecho "You have given too many variables." exit $#fi

  只要指定三个或更少的变量,该示例脚本将正常运行(并返回值 0)。如果指定了三个以上的变量,则将显示错误消息,且例程将退出 — 同时返回与命令行中给定的变量数相等的退出代码。

  对这个过程进行修改可以用来在允许运行报表之前判断当天是否是本月的最后几天:

#example8 - to see if it is near the end of the month#set `date`  # use backward quotesif [ "$3" -ge 21 ]thenecho "It is close enough to the end of the month to proceed"else echo "This report cannot be run until after the 21st of the month" exit $3fi

  在这个例子中,设置了六个变量(通过空格彼此分开):

$1 = Fri
$2 = Feb
$3 = 6
$4 = 08:56:30
$5 = EST
$6 = 2004

  这些值可以在脚本中使用,就像它们是在命令行中输入的一样。请注意,退出命令再次返回一个值 — 在这种情况下,返回的值是从 $3 的值中得到的日期。这一技巧在故障诊断时会非常有用 — 如果您认为脚本应该运行而没有运行,那么请查看 $? 的值。

  一种类似的想法可能是撰写一个只在每个月的第三个星期三运行的脚本。第三个星期三一定在该月的 15 日到 21 日之间。使用 cron,您可以调用脚本在 15 日到 21 日之间每天的一个指定时间运行,然后使用脚本的第一行检查 $1(在设置日期之后)的值是否为 Thu。如果为 Thu,那么执行剩下的脚本,如果不是,则退出。

  而另一个想法可能是,只允许脚本在超过 6:00 p.m. (18:00),所有用户都回家之后运行。只要撰写脚本,使其在值低于 18 时退出,并通过使用以下命令来获取时间(将其设为 $1)

set `date +%H`

布尔运算符

  布尔运算符在几乎每种语言中的工作方式都相同 — 包括 shell 脚本。在 nutshell 中,它们检查多个条件为真或为假,或者针对假的条件而不是真的条件采取操作。与 test 搭配使用的运算符有

! expr 如果表达式评估为假,则为真
expr1 -a expr2 如果 expr1 和 expr2 评估为真,则为真
expr1 -o expr2 如果 expr1 或 expr2 评估为真,则为真

  可以用 != 运算符代替 = 进行字符串评估。这是最简单的布尔运算符之一,对 test 的正常结果取非。

  其余两个运算符中的第一个是 -a(即 AND)运算符。要使测试最终为真,两个表达式都必须评估为真。如果任何一个评估为假,则整个测试将评估为假。例如,

$ envHOME=/LOGNAME=emmettMAIL=/usr/mail/emmettPATH=:/bin:/usr/bin:/usr/lbinTERM=linuxTZ=EST5:0EDT$$ [ "$LOGNAME" = "emmett" -a "$TERM" = "linux" ]$ echo $?0$$ [ "LOGNAME" = "karen" -a "$TERM" = "linux" ]$ echo $?1$

  在第一个评估中,两个条件都测试为真(在一个 linux 终端上登录的是 emmett),因此整个评估为真。在第二个评估中,终端检查正确但用户不正确,因此整个评估为假。

  简而言之,AND 运算符可以确保代码只在两个条件都满足时才执行。相反,只要任何一个表达式测试为真,OR (-o) 运算符即为真。我们来修改先前的例子,并将其放到一个脚本中来说明这一点:

#example9if [ "$LOGNAME" = "emmett" -o "$TERM" = "linux" ]thenecho "Ready to begin."else echo "Incorrect user and terminal." fi$ envHOME=/LOGNAME=emmettMAIL=/usr/mail/emmettPATH=:/bin:/usr/bin:/usr/lbinTERM=linuxTZ=EST5:0EDT$ example9Ready to begin.$$ LOGNAME=karen$ example9Ready to begin.$

  在脚本第一次运行时,评估判断用户是否等于 emmett。如果发现用户等于 emmett,则脚本转至 echo 语句,并跳过其余的检查。它从不检查终端是否等于 linux,因为它只需要找到一条为真的语句就可以使整个运算为真。在脚本第二次运行时,它判断用户不是 emmett,因此它将检查并发现终端确实是 linux。由于一个条件为真,脚本现在转至 echo 命令。为了引出第二条消息,两个条件都必须为假。

  在先前确定时间是否为月末的例子中,可以执行类似的检查来防止用户试图在周末运行脚本:

#example10 - Do not let the script run over the weekend#set `date`  # use backward quotesif [ "$1" = "Sat" -o "$1" = "Sun" ]thenecho "This report cannot be run over the weekend." fi

一些有用的示例

  示例 1:在脚本文件中出现的“逻辑”的最简单的形式(如本文所有示例中所示)是“if ... then”语句。先前的一个代码段检查是否存在一定数量的变量,然后将这些变量回显。假设我们对此稍微做一些修改,比如我们想回显变量,并且每次回显均减去最左边的变量,以显示一个倒的三角形。

  虽然这听起来很简单,但实际并非如此;这是您在执行大规模处理时想实现的方式:处理第一个变量、转移、处理下一个变量……

  出于演示的目的,可以按以下方式撰写脚本中的重要行:

#example11 - display declining variables, up to threeif [ "$#" -gt 3 ] # see if more than three variables are giventhenecho "You have given more than three variables." exitfiecho $*if test -n "$2"thenshiftecho $*fiif test -n "$2"thenshiftecho $*fi

  它将按以下方式执行:

$ example11 oneone$$ example11 one twoone twotwo$$ example11 one two threeone two threetwo threethree$$ example11 one two three fourYou have given more than three variables.$

  出于检查的目的将数量限制为三个变量的原因是减少在例子中要检查的行数。一切都按部就班地进行,虽然它令人难以置信地混乱;用户因使用了超过程序依设计所能处理的变量数而得到警告,且脚本退出。如果变量数为 3 或更少,则运算的核心部分开始执行。

  回显变量,执行测试以查看另一个变量是否存在。如果另一个变量存在,则执行一次转移,回显该变量,执行另一测试,等等。总共使用了 16 个有效行,而程序仅能处理不超过三个变量 — 非常混乱。假设消除变量数的限制,程序可以处理任意数量的变量。经过一些修改,脚本被缩短(美化)了,并能处理任意数量的变量:

#example12 - display declining variables, any numberwhile [ "$#" -gt 0 ]doecho $*shiftdone$ example12 1 2 3 4 5 6 7 8 9 01 2 3 4 5 6 7 8 9 02 3 4 5 6 7 8 9 03 4 5 6 7 8 9 04 5 6 7 8 9 05 6 7 8 9 06 7 8 9 07 8 9 08 9 09 00

  现在减少到只有 5 个有效行,且消除了第一个脚本三个变量的限制,并在运行时要更高效。

  示例 2:无论何时当在脚本内执行与处理相关的操作时,下一个操作将始终检查上一操作的状态,以确认它已成功完成。您可以通过检查 $? 的状态并验证它等于 0 来实现这一目的。例如,如果一个数据目录是否能访问非常重要,

#example13TEMP=LSTcd $TEMPif [ $?-ne 0 ]then echo "Data directory could not be found." Exitfi

处理错误

  test 命令常常出现的错误事实上只有两种类型。第一种是未使用正确的评估类型,例如将字符串变量与整型变量进行比较或者将带填充的字符串与不带填充的字符串进行比较。仔细评估您使用的变量将使您最终找到错误的根源,并让您能够解决这些问题。

  第二种错误类型包括将方括号误认为别名之外的某个东西。方括号与其内容之间必须有一个空格;否则,它们将不能解释其中的对象。例如,

$ [ "$LOGNAME" -gt 9]test:] missing$

  请注意,错误消息指示 test 存在问题,即使使用了别名 ]。这些问题很容易发现,因为错误消息准确地将这些问题显示出来,然后您可以增加必要的空格。

结论

  要在 shell 脚本中构建逻辑,您必须添加条件语句。每一条这种语句的核心都是对条件的评估,以判断它是否存在 — 通过使用 test 命令完成评估。了解它和它的别名(左方括号 ([)的工作原理将使您能够撰写可以完成一些复杂操作的 shell 脚本。  

33/3<123
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号