免费注册 查看新帖 |

Chinaunix

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

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

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

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

>相比较而言,使用 [[ ]] 比使用 [ ] 更可靠,建议多多使用。
我的意见两者都是可靠的,尽可以大胆使用。实际上[]的兼容性更好些,因为在bsh这样古老的shell中也能使用;[[]]则只能用于ksh及其后继者bash、zsh中。

>不过woodie兄台所提到的第 4 点 是有些遗漏的,在 [ ]中若直接使用 > < 其结果会很迷惑的。
看来shaoping兄还是没搞清楚,大概是我前面都没写清楚吧。
"<"和">"可以直接用在[[]]中。但可以直接用在[]中,只能加"\"转义后或者用引号括起后使用,否则shell就会把它解释为输入输出改向符。
看例子:
  1. $ ls 200?
  2. ls: 200?: No such file or directory
  3. $ [ 2004 < 2005 ]
  4. bash: 2005: No such file or directory
  5. $ echo $?
  6. 1
  7. $ [ 2004 > 2005 ]
  8. $ echo $?
  9. 0
  10. $ ls 200?
  11. 2005
复制代码


首先列一下目录,保证没有200?字样的文件存在。
然后执行[ 2004 < 2005 ],shell试图对文件2005作标准输入,但无法找到文件2005。
执行[ 2004 > 2005 ],系统正常执行了命令。
再列下目录,已经生成了文件2005!
再看:

  1. $ [ 2004 "<" 2006 ]&&echo true||echo false
  2. true
  3. $ [ 2004 '>' 2006 ]&&echo true||echo false
  4. false
  5. $ [ 2004 \> 2006 ]&&echo true||echo false
  6. false
复制代码

看到了吧,去掉了特殊含义的"<"和">"就表现得规规矩矩的了。

论坛徽章:
0
22 [报告]
发表于 2005-03-08 23:29 |只看该作者

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

我觉得[[和[的不同有两点:
1. [[支持模式匹配,而[不支持
2. [[测试逻辑运算要用&&或||,而[要用-a或-o

而let运算符(())主要用于算术运算和整数测试,在用于整数测试时,可以用[ -gt]等test命令替换,但建议所有算术运算和测试都用let命令实现.

论坛徽章:
0
23 [报告]
发表于 2005-03-24 21:06 |只看该作者

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

学到新知识,好文章!!

论坛徽章:
0
24 [报告]
发表于 2005-12-26 14:17 |只看该作者
要总结消化才行啊。我这里每次测试的 ">;"都是提示错误如下:

  1. [root@PostFix shell]# [ d>;c ]&&echo ok||echo fail
  2. [root@PostFix shell]#-bash: syntax error near unexpected token `;'
复制代码

然后用了转义"\"同样的出现错误

  1. [root@PostFix shell]# [ d\>;c ]&&echo ok||echo fail
  2. bash: [: missing `]'
  3. -bash: c: command not found
  4. fail
复制代码

而直接用 "\"+">"即 "\>"就可以实现了哦。

  1. [root@PostFix shell]# [ d\>c ]&&echo ok||echo fail
  2. ok
复制代码


这样反而OK,我是在redhat as3下面的bash环境下测试的。为何和你们所说的不一样呢?

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
25 [报告]
发表于 2005-12-26 14:29 |只看该作者
原帖由 佛光普照 于 2005-12-26 14:17 发表
要总结消化才行啊。我这里每次测试的 ">;"都是提示错误如下:

[code][root@PostFix shell]# [ d>;c ]&&echo ok||echo fail
[root@PostFix shell]#-bash: syntax error near unexpect ...

[]对于逻辑判断,要远远不如用[[]],因此推加使用[[]]

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
26 [报告]
发表于 2005-12-26 15:49 |只看该作者
原帖由 佛光普照 于 2005-12-26 14:17 发表
要总结消化才行啊。我这里每次测试的 ">;"都是提示错误如下:
...

呵呵,这个难怪你搞糊涂了。原贴中的">"后面并没有“;”,可能是论坛系统升级后系统在后台作转换时有点bug吧。这个有点shell常识的应该看得出来,不过初学者就难免莫名其妙了。这一点还请大家阅读时注意。
这个应该烦请版主示下:到底应该怎样消除这个错误?最好是修改程序,免得跟帖的每个人都重新修改。有的网友可能已经很久不来了。

我还是先修改一下自己的帖子吧。对大家造成的误导和困扰,对不起了!

我的三个帖子,原样贴在下面,请参考。不便之处,请大家原谅!shaoping兄或其他人的帖子,最好还是请本人修改。

[ 本帖最后由 woodie 于 2005-12-26 16:28 编辑 ]

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

16楼的克隆:

###请大家注意:
#可能是论坛系统升级后系统在后台作转换时有点bug吧。本人的帖子中的“>”后奇怪的多了以各分号“;”,造成有的网友阅读时的混淆和困扰。详见25楼佛光普照兄的帖子。在此woodie跟大家say sorry了!我把自己16楼的帖子原样搬到这里,去掉了那些些莫名其妙多出来的“;”。特此说明。以下是16楼的内容:

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
复制代码

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

19楼的克隆:

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不是很熟。

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

22楼的克隆:

>相比较而言,使用 [[ ]] 比使用 [ ] 更可靠,建议多多使用。
我的意见两者都是可靠的,尽可以大胆使用。实际上[]的兼容性更好些,因为在bsh这样古老的shell中也能使用;[[]]则只能用于ksh及其后继者bash、zsh中。

>不过woodie兄台所提到的第 4 点 是有些遗漏的,在 [ ]中若直接使用 > < 其结果会很迷惑的。
看来shaoping兄还是没搞清楚,大概是我前面都没写清楚吧。
"<"和">"可以直接用在[[]]中。但可以直接用在[]中,只能加"\"转义后或者用引号括起后使用,否则shell就会把它解释为输入输出改向符。
看例子:
  1. $ ls 200?
  2. ls: 200?: No such file or directory
  3. $ [ 2004 < 2005 ]
  4. bash: 2005: No such file or directory
  5. $ echo $?
  6. 1
  7. $ [ 2004 > 2005 ]
  8. $ echo $?
  9. 0
  10. $ ls 200?
  11. 2005
复制代码


首先列一下目录,保证没有200?字样的文件存在。
然后执行[ 2004 < 2005 ],shell试图对文件2005作标准输入,但无法找到文件2005。
执行[ 2004 > 2005 ],系统正常执行了命令。
再列下目录,已经生成了文件2005!
再看:

  1. $ [ 2004 "<" 2006 ]&&echo true||echo false
  2. true
  3. $ [ 2004 '>' 2006 ]&&echo true||echo false
  4. false
  5. $ [ 2004 \> 2006 ]&&echo true||echo false
  6. false
复制代码

看到了吧,去掉了特殊含义的"<"和">"就表现得规规矩矩的了。

论坛徽章:
0
30 [报告]
发表于 2006-03-15 09:16 |只看该作者
不错哦,又学到一点了!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP