shell中if条件字符串、数字比对,[[ ]]和[ ]区别

来源:互联网 发布:优化储存空间照片恢复 编辑:程序博客网 时间:2024/05/16 14:00

一. shell中if条件字符串、数字比对

先说 [ ] 和test,两者是一样的,在命令行里test expr和 [ expr ] 的效果相同。test的三个基本作用是判断文件、判断字符串、判断整数。支持使用与或非将表达式连接起来。

要注意的有:

test中可用的比较运算符只有 == 和 != ,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用 

-eq ,  -gt 这种形式。无论是字符串比较还是整数比较都千万不要使用大于号小于号。当然,如果你实在想用也是可以的,对于字符串比较可以使用尖括号的转义形式, 如果比较"ab"和"bc":[ ab \< bc ],结果为真,也就是返回状态为0.

然后是 [[ ]] ,这是内置在shell中的一个命令,它就比刚才说的test强大的多了。支持字符串的模式匹配(使用=~操作符时甚至支持shell的正则表达 式)。逻辑组合可以不使用 test 的 -a , -o 而使用 && , || 这样更亲切的形式(针对c、Java程序员)。

不用想的太复杂,基本只要记住几点:

(1)字符串比较时可以把右边的作为一个模式(这是右边的字符串不加双引号的情况下。如果右边的字符串加了双引号,则认为是一个文本字符串。),而不仅仅是一个字符串,比如 [[ hello == hell? ]] ,结果为真;
(2)使用 [ ] 和 [[ ]] 的时候不要吝啬空格,每一项两边都要有空格,[[ 1 == 2 ]] 的结果为“假”,但 [[ 1==2 ]] 的结果为“真”!后一种显然是错的;

(3)let和(()),两者也是一样的(或者说基本上是一样的,双括号比let稍弱一些)。主要进行算术运算(上面的两个都不行),也比较适合进 行整数比较,可以直接使用熟悉的<,>等比较运算符。可以直接使用变量名如var而不需要$var这样的形式。支持分号隔开的多个表达式。


二. [[ ]]和[ ]区别

1. 首先,尽管很相似,但是从概念上讲,二者是不同层次的东西。
"[[",是关键字,许多shell(如ash bsh)并不支持这种方式。ksh, bash(据说从2.02起引入对[[的支持)等支持。

"["是一条命令, 与test等价,大多数shell都支持。在现代的大多数sh实现中,"["与"test"是内部(builtin)命令,换句话说执行"test"/"["时不会调用/some/path/to/test这样的外部命令(如果有这样的命令的话)。

2.[[]]结构比Bash版本的[]更通用。在[[和]]之间的所有的字符都不会被文件扩展或是标记分割,但是会有参数引用和命令替换。

用[[ ... ]]测试结构比用[ ... ]更能防止脚本里的许多逻辑错误。比如说,&&,||,<和>操作符能在一个[[]]测试里通过,但在[]结构会发生错误。

3.(( ))结构扩展并计算一个算术表达式的值。如果表达式值为0,会返回1或假作为退出状态码。一个非零值的表达式返回一个0或真作为退出状态码。这个结构和先前test命令及[]结构的讨论刚好相反。

4.[ ... ]为shell命令,所以在其中的表达式应是它的命令行参数,所以串比较操作符">" 与"<"必须转义,否则就变成IO改向操作符了(请参看上面2中的例子)。在[[中"<"与">"不需转义;
由于"[["是关键字,不会做命令行扩展,因而相对的语法就稍严格些。例如

在[ ... ]中可以用引号括起操作符,因为在做命令行扩展时会去掉这些引号,而在[[ ... ]]则不允许这样做。

5.[[ ... ]]进行算术扩展,而[ ... ]不做

6.[[ ... && ... && ...  ]] 和 [ ... -a ... -a ...] 不一样,[[ ]] 是逻辑短路操作,而 [ ] 不会进行逻辑短路
1)在ksh中的test
数字的运算可使用let、(( )) ,其中运算时不需要变量$符号,运算符为 +、-、*、/、% ,不建议使用expr
数字的比较使用 (( )) ,其运算符 >、>=、<、<=、==、!=
可以使用算术扩展,如:(( 99+1 <= 101 ))
字符表达式的比较使用 [[ ]] ,其运算符 =、!=、-n、-z
文件表达式的测试使用 [[ ]] ,其运算符 -r、-l、-w、-x、-f、-d、-s、-nt、-ot
逻辑表达式的测试使用 [[ ]] ,其运算符 !、&&、||
数字比较、字符比较、逻辑测试可以组合,如$ [[ "a" != "b" && 4 -gt 3 ]]
支持bash中的通配符扩展,如:[[ hest = h??t ]] 、[ hest = h*t ]]

使用 (( )) 时,不需要空格分隔各值和运算符,使用 [[ ]] 时需要用空格分隔各值和运算符。

2)bash与ksh中的 [[ ]] 不同
在redhat9的bash中也可以使用 [[ ]] 符号。但是建议严格按照上面的原则使用。
在bash中,数字的比较最好使用 (( )),虽说可以使用 [[ ]],但若在其内使用运算符 >、>=、<、<=、==、!= 时,其结果经常是错误的,不过若在 [[ ]] 中使用 [ ] 中的运算符“-eq、-ne、-le、-lt、-gt、-ge”等,还尚未发现有错。因此诸如$ [[ " a" != “b” && 4 > 3 ]] 这类组合(见上)也不可以在bash中使用,其出错率很高。
例:[[ "a" != "b" && 10 > 2 ]] 判断结果就不正常。

诸如 [ 2 \< 10 ]、[[ 2 < 10 ]] 都是不要使用。使用算术扩展最好用 (( 99+1 == 100 )) ,而不要使用[[ 99+1 -eq 100 ]] 。


三. 比较

整数比较

-eq 等于,如:if [ "$a" -eq "$b" ]   -ne 不等于,如:if [ "$a" -ne "$b" ]   -gt 大于,如:if [ "$a" -gt "$b" ]   -ge 大于等于,如:if [ "$a" -ge "$b" ]   -lt 小于,如:if [ "$a" -lt "$b" ]   -le 小于等于,如:if [ "$a" -le "$b" ]   <   小于(需要双括号),如:(("$a" < "$b"))   <=  小于等于(需要双括号),如:(("$a" <= "$b"))   >   大于(需要双括号),如:(("$a" > "$b"))   >=  大于等于(需要双括号),如:(("$a" >= "$b"))   

字符串比较

= 等于,如:if [ "$a" = "$b" ]   == 等于,如:if [ "$a" == "$b" ],与=等价   

需要注意的亮点:

1)比较两个字符串是否相等的办法是:
if [ "$test"x = "test"x ]; then
这里的关键有几点:
1 使用单个等号
2 注意到等号两边各有一个空格:这是unix shell的要求
3 注意到"$test"x最后的x,这是特意安排的,因为当$test为空的时候,上面的表达式就变成了x = testx,显然是不相等的。而如果没有这个x,表达式就会报错:[: =: unary operator expected

2)==的功能在[[]]和[]中的行为是不同的

[[ $a == z* ]]   # 如果$a以"z"开头(模式匹配)那么将为true   [[ $a == "z*" ]] # 如果$a等于z*(字符匹配),那么结果为true     [ $a == z* ]     # File globbing 和word splitting将会发生   [ "$a" == "z*" ] # 如果$a等于z*(字符匹配),那么结果为true   

最后Mark一些常用参数:

-e       文件存在
-a       文件存在(已被弃用)
-f        被测文件是一个regular文件(正常文件,非目录或设备)
-s       文件长度不为0
-d       被测对象是目录
-b       被测对象是块设备
-c       被测对象是字符设备
-p       被测对象是管道
-h       被测文件是符号连接
-L       被测文件是符号连接
-S(大写)    被测文件是一个socket
-t        关联到一个终端设备的文件描述符。用来检测脚本的stdin[-t0]或[-t1]是一个终端
-r        文件具有读权限,针对运行脚本的用户
-w       文件具有写权限,针对运行脚本的用户
-x        文件具有执行权限,针对运行脚本的用户
-u        set-user-id(suid)标志到文件,即普通用户可以使用的root权限文件,通过chmod +s file实现
-k        设置粘贴位
-O        运行脚本的用户是文件的所有者
-G        文件的group-id和运行脚本的用户相同
-N         从文件最后被阅读到现在,是否被修改
f1 -nt f2        文件f1是否比f2新
f1 -ot f2        文件f1是否比f2旧
f1 -ef f2        文件f1和f2是否硬连接到同一个文件
二元比较操作符,比较变量或比较数字
整数比较:
-eq           等于              if [ "$a" -eq "$b" ]
-ne           不等于          if [ "$a" -ne "$b" ]
-gt            大于              if [ "$a" -gt "$b" ]
-ge           大于等于       if [ "$a" -ge "$b" ]
-lt             小于              if [ "$a" -lt "$b" ]
-le            小于等于       if [ "$a" -le "$b" ]
<              小于(需要双括号)    (( "$a" < "$b" ))
<=            小于等于(...)                (( "$a" <= "$b" ))
>              大于(...)                       (( "$a" > "$b" ))
>=           大于等于(...)                 (( "$a" >= "$b" ))

字符串比较:
=            等于           if [ "$a" = "$b" ]
==         与=等价
!=          不等于         if [ "$a" = "$b" ]
<            小于,在ASCII字母中的顺序:
              if [[ "$a" < "$b" ]]
               if [ "$a" \< "$b" ]         #需要对<进行转义
>            大于
-z            字符串为null,即长度为0
-n           字符串不为null,即长度不为0


0 0
原创粉丝点击