ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
总第1篇 test就是测试的意思,常用在流程控制语句中作为条件。下面做一下介绍。 ## 关于真值 与其他语言不同,Bash(包括其他Shell)中,是用0表示真,非0表示假的。 之所以用0表示成功,而不是1来表示。我认为也是有一定道理的,因为成功的情况只有一种,而出错的可能却有许多,所以用正数来表示错误。不同的正数代表着不同的错误,所以一般情况下可以通过正数的值来判断是出了什么错误。 > 如果你有过POSIX编程经验(比如Linux下C编程),你会知道一个errno的东西。你也会知道大量的if语句用来测试一个函数的调用结果,每个函数基本上都是返回0时表示操作成功,而如果返回非0则出错,此时你也要exit(0)。 下面言归正传 ## 测试整数 ### 基本规则 整数的test就是大小关系的比较,与其他语言不同,Bash中没有使用<,>来做大于等于号,而是使用了减号开头的选项来比较。 假如有两个整数变量a和b。那么比较a是否大于b,就写作`test $a -gt $b`,符合条件返回真值0。 实际在终端里测试的时候可以这样写来看test语句的执行结果: ~~~ test $a -gt $b && echo Yes ~~~ 如果条件成立打印 Yes,不成立不打印。 ### 全部选项 | 选项 | 描述 | 英文全称 | |-----|-----|-----| | eq | 等于 | equal | | gt | 大于 | greater than | | lt | 小于 | less than | | ne | 不等于 | not equal | | ge | 大于等于 | greater or equal | | le | 小于等于 | less or equal | 注意: > 每个选项前需要有一个短横线`-`。 还要注意的是使用以上操作符,那么操作符两边一定要是整数。 在Bash中,即使给整数加了引号,比如"123",也视作整数。但如果某一位含有整数[0-9]以外的字符比如,12a,"12a",则不行。 Bash脚本,或者说Shell终端中的各种命令都有很丰富的选项,所以我建议在记忆的时候要去记忆它的英文全称,理解了它的含义,这样反而会降低记忆的难度。 ## 测试字符串 字符串的测试无非就是包括,判断两个字符串是否相等,判断一个字符串是否为空。 假设str1和str2是持有两个字符串的变量(直接测试两个字符串,而非字符串变量时,则不加$,这很好理解)。具体用法为: | 用法 | 描述 | |-----|-----| | `test $str1 = $str2` | 测试是否相等,相等返回0 | | `test $str1 != $str2` | 测试是否不等,不等返回0 | | `test $str1 \< $str2` | 如果str1的字典序在str2之后,则返回0 | | `test $str1 \> $str2` | 如果str1的字典序在str2之前,则返回0 | | `test $str1` | 总是返回0 | | `test -n $str1` | 如果不为空返回0 | | `test -z $str1` | 如果是空串,返回0 | 关于字典序的那两个比较,其实就是大于号`>`和小于号`<`。因为bash中这两个符号有重定向的意思,所以这里要使用反斜杠`\` 转义。 ~~~ #在bash中一个好的习惯就是在引用变量的时候加上双引号。 ~~~ 比如下面: > **特别注意** 选项`-n`是 nonzero 的缩写,理解为**长度不为0**。**但需要特别指出的是**:-n选项测试时请将引用变量外加上双引号。 Bash中的引用变量的方法有很多种,我认为此处应该是加不加双引号无所谓的。囧。。 经测试,如果我有当前未定义变量var(*或者定义为var=""*),那么理论上讲,var就是空串。 `test -n $var`应该是返回1(假)的,因为他的长度是0。但其实此时无论var是否为空串都会返回真值0。 但是加上**双引号**(注意不能是单引号),也就是`test -n "$var"`,效果就能如期,即只有在var为空的时候返回真值0。 而选项`-z`(是 zero 的缩写,理解为**长度为0**)引用变量的时候加不加双引号无所谓。 ## 测试文件 测试文件需要用到大量的选项,这里我只写一个常用的,其他的大家自行`man test` ### 针对单个文件 | 选项 | 描述 | |-----|-----| | d | 是否为目录 | | f | 是否为普通文件 | | x | 是否有执行权限 | | r | 是否有读权限 | | w | 是否写读权限 | | e | 是否存在 | | s | 文件大小是否大于0 | | c | 是否为字符设备文件 | | b | 是否为块设备文件 | 以上条件在成立的时候返回真值0。具体用法比如: ~~~ test -f hello.c test -d /home ~~~ ### 针对两个文件 | 用法 | 描述 | |-----|-----| | test file1 -nt file2 | 测试file1的修改时间是不是比file2 new(新) | | test file1 -ot file2 | 测试file1的修改时间是不是比file2 old(旧) | | test file1 -ef file2 | 测试两者是相同的设备和具有相同的结点(inode)数 | 同样的,若是条件成立则返回真值0,否则返回假值1。注意这里的file1,file2就是文件名的字符串了。 ~~~ #可以直接test a.c -nt b.c #或者是 a=a.c b=b.c test $a -nt $b ~~~ 不再细表。 ## 逻辑运算 逻辑运算就是与或非。Bash中同样有&&,||但是并非是在test内部,而是用来组合多条shell语句,前面我们应该看到过了,只有当&&前面的语句执行成功时,才执行后面的语句。而在test内部: | 运算符 | 描述 | |-----|-----| | -a | 逻辑与 | | -o | 逻辑或 | | ! | 逻辑非 | 用法如: ~~~ test $a -lt $b -a $a -gt $c test $a -lt $b -o $a -gt $c test ! -d sleep.sh && echo Yes #如果sleep.sh不是目录,就打印Yes ~~~ 其实完整版是这样: ~~~ test $a -lt $b -a test $a -gt $c test $a -lt $b -o test $a -gt $c ~~~ ## 简化版test 在读完这一部分后,你可能会惊呼,怎么不早点告诉我。哈哈。 其实以上所有的test命令都可以用方括号替换。比如 ~~~ test -f hello.c ~~~ 可以换成 ~~~ [ -f hello.c ] ~~~ 怎么样,很方便吧。注意的是,方括号和表达式前后各有一个空格间隔哦。不要丢掉。实际也就是 [空格-f hello.c空格] 其他注意的地方是方括号的逻辑表达式,比如 ~~~ test $a -lt $b -a $a -gt $c ~~~ 可以转化为 ~~~ [ $a -lt $b -a $a -lt $c ] ~~~ 另外有一操作符 [[ ]]支持使用 &&, ||来进行表达式的逻辑运算. [ ] 与 [[ ]]两者具体差别请见:[http://www.cnblogs.com/include/archive/2011/12/09/2307905.html](http://www.cnblogs.com/include/archive/2011/12/09/2307905.html) > test是Shell的外部命令,而`[ ]`是Shell内置的操作符。 本系列(玩转Bash脚本)更多文章,请访问:[http://blog.csdn.net/column/details/wanbash.html](http://blog.csdn.net/column/details/wanbash.html)