test.docx
- 文档编号:6401003
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:12
- 大小:22.92KB
test.docx
《test.docx》由会员分享,可在线阅读,更多相关《test.docx(12页珍藏版)》请在冰豆网上搜索。
test
条件判断test
每一种条件语句的基础都是判断什么是真什么是假。
是否了解其工作原理将决定您编写的是质量一般的脚本还是您将引以为荣的脚本。
Shell脚本的能力时常被低估,但实际上其能力的发挥受制于脚本撰写者的能力。
您了解得越多,您就越能像变戏法似地撰写一个文件来使任务自动化和简化您的管理工作。
在shell脚本中进行的每一种操作(除最简单的命令编组之外)都需要检查条件。
所有的shell脚本“逻辑”—广义意义下的“逻辑”—通常都可以分为以下三大类:
if{conditionexists}then...
while{conditionexists}do...
until{conditionexists}do...
无论随后的操作是什么,这些基于逻辑的命令都依靠判断一种条件是否真实存在来决定后续的操作。
test命令是使得在每一种情况下都能够确定要判断的条件是否存在的实用工具。
因此,彻底了解这个命令对于撰写成功的shell脚本至关重要。
工作原理
test命令最短的定义可能是评估一个表达式;如果条件为真,则返回一个0值。
如果表达式不为真,则返回一个大于0的值—也可以将其称为假值。
检查最后所执行命令的状态的最简便方法是使用$?
值。
出于演示的目的,本文中的例子全部使用了这个参数。
test命令期望在命令行中找到一个参数,当shell没有为变量赋值时,则将该变量视为空。
这意味着在处理脚本时,一旦脚本寻找的参数不存在,则test将报告该错误。
当试图保护脚本时,您可以通过将所有参数包含在双引号中来解决这个问题。
然后shell将变量展开,如果变量没有值,那么将传递一个空值给test。
另一种方法是在脚本内增加一个额外检查过程来判断是否设置了命令行参数。
如果没有设置命令行参数,那么脚本会告诉用户缺少参数,然后退出。
我们会通过一些例子来更具体地说明所有这些内容。
test和[命令
虽然Linux和UNIX的每个版本中都包含test命令,但该命令有一个更常用的别名—左方括号:
[。
test及其别名通常都可以在/usr/bin或/bin(取决于操作系统版本和供应商)中找到。
当您使用左方括号而非test时,其后必须始终跟着一个空格、要评估的条件、一个空格和右方括号。
右方括号不是任何东西的别名,而是表示所需评估参数的结束。
条件两边的空格是必需的,这表示要调用test,以区别于同样经常使用方括号的字符/模式匹配操作。
test和[的语法如下:
testexpression
[expression]
在这两种情况下,test都评估一个表达式,然后返回真或假。
如果它和if、while或until命令结合使用,则您可以对程序流进行广泛的控制。
不过,您无需将test命令与任何其它结构一起使用;您可以从命令行直接运行它来检查几乎任何东西的状态。
因为它们彼此互为别名,所以使用test或[均需要一个表达式。
表达式一般是文本、数字或文件和目录属性的比较,并且可以包含变量、常量和运算符。
运算符可以是字符串运算符、整数运算符、文件运算符或布尔运算符—我们将在以下各部分依次介绍每一种运算符。
test文件运算符
利用这些运算符,您可以在程序中根据对文件类型的评估结果执行不同的操作:
-bfile如果文件为一个块特殊文件,则为真
-cfile如果文件为一个字符特殊文件,则为真
-dfile如果文件为一个目录,则为真
-efile如果文件存在,则为真
-ffile如果文件为一个普通文件,则为真
-gfile如果设置了文件的SGID位,则为真
-Gfile如果文件存在且归该组所有,则为真
-kfile如果设置了文件的粘着位,则为真
-Ofile如果文件存在并且归该用户所有,则为真
-pfile如果文件为一个命名管道,则为真
-rfile如果文件可读,则为真
-sfile如果文件的长度不为零,则为真
-Sfile如果文件为一个套接字特殊文件,则为真
-tfd如果fd是一个与终端相连的打开的文件描述符(fd默认为1),则为真
-ufile如果设置了文件的SUID位,则为真
-wfile如果文件可写,则为真
-xfile如果文件可执行,则为真
以下示例显示了此简单操作的运行情况:
$ls-l
total33
drwxr-xr-w2rootroot1024Dec505:
05LST
-rw-rw-rw-1emmettusers27360Feb607:
30evan
-rwsrwsrwx1rootroot152Feb607:
32hannah
drwxr-xr-x2emmettusers1024Feb607:
31karen
-rw-------1emmettusers152Feb607:
29kristin
-rw-r--r--1emmettusers152Feb607:
29spencer
$
$test-revan
$echo$?
0
$test-rwalter
$echo$?
1
$
由于第一次评估为真—文件存在且可读—返回值为真,或0。
由于第二次评估的文件不存在,该值为假,返回值不为零。
将值指定为零或非零很重要,因为在失败时不会始终返回1(虽然这是通常返回的值),可能返回一个非零值。
正如开头所提到的,除了使用test外,您还可以用方括号[]将命令括住来向shell发出同样的命令—如下所示:
$[-wevan]
$echo$?
0
$[-xevan]
$echo$?
1
$
同样,第一个表达式为真,第二个表达式为假—正如返回值所指示的那样。
您还可以使用以下命令将两个文件彼此进行比较:
file1-effile2测试以判断两个文件是否与同一个设备相连,是否拥有相同的inode编号
file1-ntfile2测试以判断第一个文件是否比第二个文件更新(由修改日期决定)
file1-otfile2测试以判断第一个文件是否比第二个文件更旧
以下示例显示了使用这些运算符比较文件的结果:
$[evan-ntspencer]
$echo$?
0
$[karen-otspencer]
$echo$?
1
$
名为evan的文件比名为spencer的文件更新,因而评估为真。
类似地,名为karen的文件比名为spencer的文件更新,因此该评估为假。
字符串比较运算符
如标题所示,这组函数比较字符串的值。
您可以检查它们是否存在、是否相同或者是否不同。
String测试以判断字符串是否不为空
-nstring测试以判断字符串是否不为空;字符串必须为test所识别
-zstring测试以判断字符串是否为空;字符串必须为test所识别
string1=string2测试以判断string1是否与string2相同
string1!
=string2测试以判断string1是否与string2不同
对任何变量进行的最有用的测试之一是判断它的值是否不为空,可以简单地将其放在test命令行中执行这种测试,如下例所示:
$test"$variable"
强烈建议进行此种测试时用双引号将变量括住,以让shell识别变量(即使变量为空)。
默认情况下执行的基本字符串评估和-n测试从功能上讲是相同的,如以下示例所示:
#example1
iftest-n"$1"
then
echo"$1"
fi
执行以上例子中的代码将根据$1是否存在给出以下结果:
$example1friday
friday
$
$example1
$
如果将代码更改为以下形式,则结果将相同:
#example2
iftest"$1"
then
echo"$1"
fi
如下所示:
$example2friday
friday
$
$example2
$
所有这些表明,通常不需要-n,它代表默认操作。
要从一个不同的角度来查看各种可能性,您可以用另一个选项来替换-n,并检查该值是否为空(相对于非空)。
这可以用-z选项来实现,代码为:
#example3
iftest-z"$1"
then
echo"novalueswerespecified"
fi
运行如下:
$example3
novalueswerespecified
$example3friday
$
如果在没有命令行参数的情况下运行该程序,而表达式评估为真,那么将执行程序块中的文本。
如果在命令行中有值,则脚本退出,不执行任何操作。
将评估操作放在脚本的开头非常有用,这可以在可能产生错误的进一步处理之前预先检查变量值。
其余的字符串运算符对两个变量/字符串之间的精确匹配或其中的差异(您也可以称之为等价性和“不等价性”)进行评估。
第一个例子对匹配进行测试:
$env
LOGNAME=emmett
PAGER=less
SHELL=/bin/bash
TERM=linux
$
$["$LOGNAME"="emmett"]
$echo$?
0
$
$["$LOGNAME"="kristin"]
$echo$?
1
$
或者,该评估可以以脚本的形式用于决定是否运行脚本:
#example4
if["$LOGNAME"="emmett"]
then
echo"processingbeginning"
else
echo"incorrectuser"
fi
这种方法可以用来寻找任意的值(如终端类型或shell类型),在允许脚本运行之前这些值必须匹配。
请注意,=或!
=运算符的优先级高于其它大多数可指定选项,且要求必须伴有表达式。
因此,除了比较字符串的选项之外,=或!
=都不能和检查某种东西(如可读文件、可执行文件或目录)的存在性的选项一起使用。
整数比较运算符
正如字符串比较运算符验证字符串相等或不同一样,整数比较运算符对数字执行相同的功能。
如果变量的值匹配则表达式测试为真,如果不匹配,则为假。
整数比较运算符不处理字符串(正如字符串运算符不处理数字一样):
int1-eqint2如果int1等于int2,则为真
int1-geint2如果int1大于或等于int2,则为真
int1-gtint2如果int1大于int2,则为真
int1-leint2如果int1小于或等于int2,则为真
int1-ltint2如果int1小于int2,则为真
int1-neint2如果int1不等于int2,则为真
以下示例显示了一个代码段,其中在命令行中给出的值必须等于7:
#example5
if[$1-eq7]
then
echo"You'veenteredthemagicnumber."
else
echo"You'veenteredthewrongnumber."
fi
运行中:
$example56
You'veenteredthewrongnumber.
$
$example57
You'veenteredthemagicnumber.
$
和字符串一样,比较的值可以是在脚本外为变量赋的值,而不必总是在命令行中提供。
以下示例演示了实现这一点的一种方法:
#example6
if[$1-gt$number]
then
echo"Sorry,but$1istoohigh."
else
echo"$1willwork."
fi
$setnumber=7
$exportnumber
$example68
Sorry,but8istoohigh.
$example67
7willwork.
$
整数比较运算符最佳的用途之一是评估指定的命令行变量的数目,并判断它是否符合所要求的标准。
例如,如果某个特定的命令只能在有三个或更少变量的情况下运行,
#example7-displayvariables,uptothree
if["$#"-gt3]
then
echo"Youhavegiventoomanyvariables."
exit$#
fi
只要指定三个或更少的变量,该示例脚本将正常运行(并返回值0)。
如果指定了三个以上的变量,则将显示错误消息,且例程将退出—同时返回与命令行中给定的变量数相等的退出代码。
对这个过程进行修改可以用来在允许运行报表之前判断当天是否是本月的最后几天:
#example8-toseeifitisneartheendofthemonth#
set`date`#usebackwardquotes
if["$3"-ge21]
then
echo"Itiscloseenoughtotheendofthemonthtoproceed"
else
echo"Thisreportcannotberununtilafterthe21stofthemonth"
exit$3
fi
在这个例子中,设置了六个变量(通过空格彼此分开):
$1=Fri
$2=Feb
$3=6
$4=08:
56:
30
$5=EST
$6=2004
这些值可以在脚本中使用,就像它们是在命令行中输入的一样。
请注意,退出命令再次返回一个值—在这种情况下,返回的值是从$3的值中得到的日期。
这一技巧在故障诊断时会非常有用—如果您认为脚本应该运行而没有运行,那么请查看$?
的值。
一种类似的想法可能是撰写一个只在每个月的第三个星期三运行的脚本。
第三个星期三一定在该月的15日到21日之间。
使用cron,您可以调用脚本在15日到21日之间每天的一个指定时间运行,然后使用脚本的第一行检查$1(在设置日期之后)的值是否为Thu。
如果为Thu,那么执行剩下的脚本,如果不是,则退出。
而另一个想法可能是,只允许脚本在超过6:
00p.m.(18:
00),所有用户都回家之后运行。
只要撰写脚本,使其在值低于18时退出,并通过使用以下命令来获取时间(将其设为$1)
set`date+%H`
布尔运算符
布尔运算符在几乎每种语言中的工作方式都相同—包括shell脚本。
在nutshell中,它们检查多个条件为真或为假,或者针对假的条件而不是真的条件采取操作。
与test搭配使用的运算符有
!
expr如果表达式评估为假,则为真
expr1-aexpr2如果expr1和expr2评估为真,则为真
expr1-oexpr2如果expr1或expr2评估为真,则为真
可以用!
=运算符代替=进行字符串评估。
这是最简单的布尔运算符之一,对test的正常结果取非。
其余两个运算符中的第一个是-a(即AND)运算符。
要使测试最终为真,两个表达式都必须评估为真。
如果任何一个评估为假,则整个测试将评估为假。
例如,
$env
HOME=/
LOGNAME=emmett
MAIL=/usr/mail/emmett
PATH=:
/bin:
/usr/bin:
/usr/lbin
TERM=linux
TZ=EST5:
0EDT
$
$["$LOGNAME"="emmett"-a"$TERM"="linux"]
$echo$?
0
$
$["LOGNAME"="karen"-a"$TERM"="linux"]
$echo$?
1
$
在第一个评估中,两个条件都测试为真(在一个linux终端上登录的是emmett),因此整个评估为真。
在第二个评估中,终端检查正确但用户不正确,因此整个评估为假。
简而言之,AND运算符可以确保代码只在两个条件都满足时才执行。
相反,只要任何一个表达式测试为真,OR(-o)运算符即为真。
我们来修改先前的例子,并将其放到一个脚本中来说明这一点:
#example9
if["$LOGNAME"="emmett"-o"$TERM"="linux"]
then
echo"Readytobegin."
else
echo"Incorrectuserandterminal."
fi
$env
HOME=/
LOGNAME=emmett
MAIL=/usr/mail/emmett
PATH=:
/bin:
/usr/bin:
/usr/lbin
TERM=linux
TZ=EST5:
0EDT
$example9
Readytobegin.
$
$LOGNAME=karen
$example9
Readytobegin.
$
在脚本第一次运行时,评估判断用户是否等于emmett。
如果发现用户等于emmett,则脚本转至echo语句,并跳过其余的检查。
它从不检查终端是否等于linux,因为它只需要找到一条为真的语句就可以使整个运算为真。
在脚本第二次运行时,它判断用户不是emmett,因此它将检查并发现终端确实是linux。
由于一个条件为真,脚本现在转至echo命令。
为了引出第二条消息,两个条件都必须为假。
在先前确定时间是否为月末的例子中,可以执行类似的检查来防止用户试图在周末运行脚本:
#example10-Donotletthescriptrunovertheweekend#
set`date`#usebackwardquotes
if["$1"="Sat"-o"$1"="Sun"]
then
echo"Thisreportcannotberunovertheweekend."
fi
一些有用的示例
示例1:
在脚本文件中出现的“逻辑”的最简单的形式(如本文所有示例中所示)是“if...then”语句。
先前的一个代码段检查是否存在一定数量的变量,然后将这些变量回显。
假设我们对此稍微做一些修改,比如我们想回显变量,并且每次回显均减去最左边的变量,以显示一个倒的三角形。
虽然这听起来很简单,但实际并非如此;这是您在执行大规模处理时想实现的方式:
处理第一个变量、转移、处理下一个变量……
出于演示的目的,可以按以下方式撰写脚本中的重要行:
#example11-displaydecliningvariables,uptothree
if["$#"-gt3]#seeifmorethanthreevariablesaregiven
then
echo"Youhavegivenmorethanthreevariables."
exit
fi
echo$*
iftest-n"$2"
then
shift
echo$*
fi
iftest-n"$2"
then
shift
echo$*
fi
它将按以下方式执行:
$example11one
one
$
$example11onetwo
onetwo
two
$
$example11onetwothree
onetwothree
twothree
three
$
$example11onetwothreefour
Youhavegivenmorethanthreevariables.
$
出于检查的目的将数量限制为三个变量的原因是减少在例子中要检查的行数。
一切都按部就班地进行,虽然它令人难以置信地混乱;用户因使用了超过程序依设计所能处理的变量数而得到警告,且脚本退出。
如果变量数为3或更少,则运算的核心部分开始执行。
回显变量,执行测试以查看另一个变量是否存在。
如果另一个变量存在,则执行一次转移,回显该变量,执行另一测试,等等。
总共使用了16个有效行,而程序仅能处理不超过三个变量—非常混乱。
假设消除变量数的限制,程序可以处理任意数量的变量。
经过一些修改,脚本被缩短(美化)了,并能处理任意数量的变量:
#example12-displaydecliningvariables,anynumber
while["$#"-gt0]
do
echo$*
shift
done
$example121234567890
1234567890
234567890
34567890
4567890
567890
67890
7890
890
90
0
现在减少到只有5个有效行,且消除了第一个脚本三个变量的限制,并在运行时要更高效。
示例2:
无论何时当在脚本内执行与处理相关的操作时,下一个操作将始终检查上一操作的状态,以确认它已成功完成。
您可以通过检查$?
的状态并验证它等于0来实现这一目的。
例如,如果一个数据目录是否能访问非常重要,
#example13
TEMP=LST
cd$TEMP
if[$?
-ne0]
then
echo"Datadirectorycouldnotbefound."
Exit
fi
处理错误
资源
下载针对Linux的Oracle数据库10g
Oracle数据库10g第1版(10.1.0.2)现在可用于Linuxx86和LinuxItanium平台;请在此从OTN上免费下载。
访问Linux技术中心
收藏本页,以获取关于Linux系统管理员最佳应用的一般技术信息,以及关于Oracle-on-Linux产品群的具体技术信息。
相关文章
Linux相关技术文章的存档
test命令常常出现的错误事实上只有两种类型。
第一种是未使用正确的评估类型,例如将字符串变量与整型变量进行比较或者将带填充的字符串与不带填充的字符串进行比较。
仔细评估您使用的变量将使您最终找到错误的根源,并让您能够解决这些问题。
第二种错误类型包括将方括号误认为别名之外的某个东西。
方括号与其内容之间必须有一个空格;否则,它们将不能解释其中的对象。
例如,
$["$LOGNAME"-gt9]
test:
]missing
$
请注意,错误消息指示test存在问题,即使使用了别名]。
这些问题很容易发现,因为错误消息准确地将这些问题显示出来
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- test
![提示](https://static.bdocx.com/images/bang_tan.gif)