免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: zhouhaiming
打印 上一主题 下一主题

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊  关闭 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2004-03-29 20:57 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

[quote]原帖由 "panlm"]是shell的内置命令[/quote 发表:

在ksh的惯例,[[...]]是对字符类变量进行判断,而对数字变量的判断则用((...)),当然,这不过是一个惯例而已,便于清晰的阅读代码,别的shell我不敢妄加评论,对ksh,我还是比较"在行"的

论坛徽章:
0
12 [报告]
发表于 2004-03-30 09:23 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

[[]] 可以对字符串进行大小比较,基于字典顺序的比较。

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
13 [报告]
发表于 2004-03-31 19:01 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

顶一下!

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
14 [报告]
发表于 2004-03-31 19:04 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

对不起,发重了,删掉这一贴。

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
15 [报告]
发表于 2004-03-31 19:07 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

1. 首先,尽管很相似,但是从概念上讲,二者是不同层次的东西。
"[[",是关键字,许多shell(如ash bsh)并不支持这种方式。ksh, bash(据说从2.02起引入对[[的支持)等支持。
"["是一条命令, 与test等价,大多数shell都支持。在现代的大多数sh实现中,"["与"test"是内部(builtin)命令,换句话说执行"test"/"["时不会调用/some/path/to/test这样的外部命令(如果有这样的命令的话)。
下面是在rh7.3下的测试结果,GNU bash, version 2.05a.0(1),安装了sh-utils。
  1. $ type test
  2. test is a shell builtin
  3. $ type [
  4. [ is a shell builtin
  5. $ rpm -ql sh-utils|grep test
  6. /usr/bin/test
  7. /usr/share/man/man1/test.1.gz
  8. $ ls -l `which test`
  9. -rwxr-xr-x    1 root     root        20424  4月  9  2002 /usr/bin/test
  10. ls -l $(which [)
  11. lrwxrwxrwx    1 root     root            4  8月 23  2002 /usr/bin/[ -> test
复制代码

在你的机器上结果可能会有所不同哦。

2. 相同的地方是二者都支持算术比较和字符串比较表达式。
举例(测试环境bash 2.05b.0(1),下同):
  1. $ [ 2 -lt 10 ]&&echo true&&echo false
  2. true
  3. $  [ 2 -gt 10 ]&&echo true||echo false
  4. false
  5. $  [ 2 \< 10 ]&&echo true||echo false  #you should use "\<"
  6. false
  7. $  [ 2 \> 10 ]&&echo true||echo false  #you should use "\>"
  8. true
复制代码
  1. $  [[ 2 -gt 10 ]]&&echo true||echo false
  2. false
  3. $  [[ 2 -lt 10 ]]&&echo true||echo false
  4. true
  5. $  [[ 2 < 10 ]]&&echo true||echo false
  6. false
  7. $  [[ 2 > 10 ]]&&echo true||echo false
  8. true
复制代码
  1. $ [ test = test ]&&echo true||echo false  #normal compare
  2. true
  3. $ [ test = t*t ]&&echo true||echo false  #pattern match.
  4. true
  5. $ [ test = t..t ]&&echo true||echo false  #not match.
  6. false
  7. $ [ test = t??t ]&&echo true||echo false  #note that "?", not "." stands for one single character here
  8. true
  9. $ [ test = "t??t" ]&&echo true||echo false #alert: don't quote the pattern
  10. false
复制代码
  1. $ [[ test = test ]]&&echo true||echo false  #normal compare
  2. true
  3. $ [[ test = t*t ]]&&echo true||echo false  #pattern match.
  4. true
  5. $ [[ test = t..t ]]&&echo true||echo false  #not match.
  6. false
  7. $ [[ test = t??t ]]&&echo true||echo false  #note that "?", not "." stands for one single character here
  8. true
  9. $ [[ test = "t??t" ]]&&echo true||echo false #alert: don't quote the pattern
  10. false
复制代码

说明:
"-gt", "-lt"是算术比较操作符,用于比较整数的大小。

">", "<"是字符串比较操作符,用于比较字符串的大小,使用字典顺序,与当前的locale有关。

另外,"="还可以做简单的模式匹配,与一般的正则表达式不同,这里的模式匹配要简单得多,类似文件名的统配符的扩展规则。还要注意等号右端的模式不能用引号括起。

第2点是谈相同点,以下的都是二者"行为上"的不同点。

3. [[的行为相对地更接近于其他语言,例如"&&"而不是"-a"表示逻辑"与",用"||"而不是"-o"表示逻辑"或"。
例如:
  1. $ [[ 1 < 2 && b > a ]]&&echo true||echo false
  2. true
  3. $ [[ 1 < 2 -a b > a ]]&&echo true||echo false
  4. bash: syntax error in conditional expression
  5. bash: syntax error near `-a'
  6. $ [ 1 < 2 -a b > a ]&&echo true||echo false
  7. true
  8. $ [ 1 < 2 && b > a ]&&echo true||echo false  #wrong syntax
  9. bash: [: missing `]'
  10. false
  11. $ [ 1 < 2 \&\& b > a ]&&echo true||echo false  #aslo wrong
  12. bash: [: &&: binary operator expected
  13. false
复制代码


4. [ ... ]为shell命令,所以在其中的表达式应是它的命令行参数,所以串比较操作符">" 与"<"必须转义,否则就变成IO改向操作符了(请参看上面2中的例子)。在[[中"<"与">"不需转义;
由于"[["是关键字,不会做命令行扩展,因而相对的语法就稍严格些。例如
在[ ... ]中可以用引号括起操作符,因为在做命令行扩展时会去掉这些引号,而在[[ ... ]]则不允许这样做。
举例:
  1. $ [ "-z" "" ]&&echo true||echo false
  2. true
  3. $ [ -z "" ]&&echo true||echo false
  4. true
  5. $ [[ "-z" "" ]]&&echo true||echo false
  6. bash: conditional binary operator expected
  7. bash: syntax error near `""'
  8. $ [[ -z "" ]]&&echo true||echo false
  9. true
复制代码



5. [[ ... ]]进行算术扩展,而[ ... ]不做。
举例:
  1. $ [[ 99+1 -eq 100 ]]&&echo true||echo false
  2. true
  3. $ [ 99+1 -eq 100 ]&&echo true||echo false
  4. bash: [: 99+1: integer expression expected
  5. false
  6. $ [ $((99+1)) -eq 100 ]&&echo true||echo false
  7. true
复制代码

论坛徽章:
0
16 [报告]
发表于 2005-01-10 16:16 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

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 ]] 。

论坛徽章:
0
17 [报告]
发表于 2005-01-10 19:47 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

受益匪浅,谢谢大家见仁见智!

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
18 [报告]
发表于 2005-01-11 14:34 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

shaoping0330的钻研精神让人佩服。我再补充几点:

1.((...))等价于let,专门用来进行算术运算、比较,bsh中也可以使用,而且最妙的是它支持C风格的运算符。要取得算术表达式的值时可以用"$((expression))"形式
举例:

  1. $ ((i=1+99)) ; echo $i
  2. 100
  3. $ echo $((i++))
  4. 101
  5. $ echo $((--i))
  6. 100
  7. $ echo $((2**3))
  8. 8
  9. $ echo $((5%3))
  10. 2
  11. $ echo $((1<2?10:20))
  12. 10
复制代码


2.test等价于[],与[[]]相似但有些区别;既可用于算术运算、比较又可用于字符串、文件测试。算术比较用 -eq, -lt, -gt, -le, -ge,字符串比较用<, >, =, !=, >=和<=这两个是无效的。[]中逻辑运算用:-a, -o,而[[中用&&, ||;[[不能用于bsh,但可用在ksh/bash/zsh中。

3.正如我在以前的帖子中指出的,可以把[...]看作一个shell命令,方括号中的内容就是命令行参数。所以"<"、">"并不是不可以用在[...]中,只不过他们是shell的"元字符",使用前必须用"\"转义,去掉其特殊含义就可以了。

4.关于字符串比较。[...]、[[...]]中都可以对字符串进行比较,比较的顺序是"字典顺序"。对ascii字符来讲,码表中排列在前的较小,如A<B,A<a, 1<2。再强调一次,这里只要用了"<"、">",就表示是字符串比较,那么9 > 100为真,因为这实际上等价于‘9’ > ‘100’,9在码表中排在1后面,所以字符串"9"大于字符串"100"。只要搞清楚了何时是算术比较,何时是串比较,一般就不会出错了。至于不要使用"<"、">"的意见,我不能苟同。:)

5.((...))的结构对于算术运算应该大力提倡,这一点我非常赞成。

6.shaoping说[[在bash与ksh中不同,是指什么?请指教。我对ksh不是很熟。

论坛徽章:
0
19 [报告]
发表于 2005-01-12 17:03 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

更正:在ksh和bash-2.05b,[[ ]]是一样。至少在我目前的相关测试中!


数字测试        -eq -ne -lt -le -gt -ge         [[ ]]同 [ ]
文件测试        -r、-l、-w、-x、-f、-d、-s、-nt、-ot         [[ ]]同 [ ]
字符串测试        =  !=  -n  -z        [[ ]]同 [ ]
逻辑测试        []为 -a -o !         [[ ]] 为&&  || !
数学运算        [] 不可以使用        [[ ]]可以使用+  -  *  /  %
组合        均可用各自逻辑符号连接的数字(运算)测试、文件测试、字符测试

情况比较复杂的是字符的测试:字符测试
==        同=        [ ]与[[ ]]同       
<= >=        同=均不可以使用
< >        在 [] 内比较结果异常,如:$ [ 44 > 45 ] 与 $ [ 45 > 44 ]的返回值一样$ [ ccca > ccccb ]与$ [ ccccb > ccca ]的返回值一样       
< >(首个单挑)        在[[]] 根据相应ASCII码比较(如果是多个字母或数字组合,则先比较首个,若相同则接着比较下一个)
\> \<(首个单挑)        在 [] 内根据相应ASCII码比较(如果是多个字母或数字组合,则先比较首个,若相同则接着比较下一个)       
\> \<        在 [[]] 不可以使用

redhat9:bash-2.05b下测试(下图)

未命名.gif (10.64 KB, 下载次数: 128)

未命名.gif

论坛徽章:
0
20 [报告]
发表于 2005-01-12 17:18 |只看该作者

请问替代test语句的[ ]和[[ ]]表达式有什么区别啊

相比较而言,使用 [[ ]] 比使用 [ ] 更可靠,建议多多使用。
不过对于数字的运算和测试,建议大家都使用  (( )) ,这样更一目了然!

我以前看的shell资料,字符的比较一直都只说了 = != -n -z 这几个,看了woodie兄台所提到的第 4 点,才发现自己 ~~~ “关在圈子里出不去了”
补充了   大于 小于 的比较,字符的测试也就差不多完整了!

不过woodie兄台所提到的第 4 点 是有些遗漏的,在 [ ]中若直接使用 > < 其结果会很迷惑的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP