请问 if [[ -f $(which stardict) ]] 中的 [[ ]] 是什么意思?test =[ ]

sh/bash/dash/ksh/zsh等Shell脚本
回复
fujianbo1984
帖子: 3
注册时间: 2006-09-15 15:49

请问 if [[ -f $(which stardict) ]] 中的 [[ ]] 是什么意思?test =[ ]

#1

帖子 fujianbo1984 » 2007-12-18 10:18

请问 if [[ -f $(which stardict) ]] 中的 [[ ]] 是什么意思?
test 不是用[ ] 代替的吗?
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

#2

帖子 eexpress » 2007-12-18 10:24

是手哆嗦了。

[ -f `which stardict` ] && xxxxxxx吧。简单

这句子有逻辑错误的啊。既然which了。 还-f作什么。哪里抄的哦。
● 鸣学
fujianbo1984
帖子: 3
注册时间: 2006-09-15 15:49

#3

帖子 fujianbo1984 » 2007-12-19 9:12

是那个自动安装stardict 及下载字典的脚本的

在oracle xe 的 nsl_lang.sh也有这样的语句

if [[ -n "$LC_ALL" ]] ; then
locale=$LC_ALL
elif [[ -n "$LANG" ]] ; then
locale=$LANG
else
locale=
fi
头像
iblicf
帖子: 3766
注册时间: 2007-01-15 17:15

#4

帖子 iblicf » 2007-12-19 9:22

iblicf@ubuntu:~$ type '['
[ is a shell builtin
iblicf@ubuntu:~$ type '[['
[[ is a shell keyword
iblicf@ubuntu:~$


LOOK-->《高级Bash脚本编程指南》[3.7版本]
fujianbo1984
帖子: 3
注册时间: 2006-09-15 15:49

#5

帖子 fujianbo1984 » 2007-12-19 10:13

网上找到一段讨论,看得有点晕

---------------------------------------------------
woodie 回复于:2005-12-26 16:17:07
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。

$ type test

test is a shell builtin

$ type [

[ is a shell builtin

$ rpm -ql sh-utils|grep test

/usr/bin/test

/usr/share/man/man1/test.1.gz

$ ls -l `which test`

-rwxr-xr-x 1 root root 20424 4月 9 2002 /usr/bin/test

ls -l $(which [)

lrwxrwxrwx 1 root root 4 8月 23 2002 /usr/bin/[ -> test



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



2. 相同的地方是二者都支持算术比较和字符串比较表达式。

举例(测试环境bash 2.05b.0(1),下同):

$ [ 2 -lt 10 ]&&echo true&&echo false

true

$ [ 2 -gt 10 ]&&echo true||echo false

false

$ [ 2 \< 10 ]&&echo true||echo false #you should use "\<"

false

$ [ 2 \> 10 ]&&echo true||echo false #you should use "\>"

true



$ [[ 2 -gt 10 ]]&&echo true||echo false

false

$ [[ 2 -lt 10 ]]&&echo true||echo false

true

$ [[ 2 < 10 ]]&&echo true||echo false

false

$ [[ 2 > 10 ]]&&echo true||echo false

true



$ [ test = test ]&&echo true||echo false #normal compare

true

$ [ test = t*t ]&&echo true||echo false #pattern match.

true

$ [ test = t..t ]&&echo true||echo false #not match.

false

$ [ test = t??t ]&&echo true||echo false #note that "?", not "." stands for one single character here

true

$ [ test = "t??t" ]&&echo true||echo false #alert: don't quote the pattern

false



$ [[ test = test ]]&&echo true||echo false #normal compare

true

$ [[ test = t*t ]]&&echo true||echo false #pattern match.

true

$ [[ test = t..t ]]&&echo true||echo false #not match.

false

$ [[ test = t??t ]]&&echo true||echo false #note that "?", not "." stands for one single character here

true

$ [[ test = "t??t" ]]&&echo true||echo false #alert: don't quote the pattern

false



说明:

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



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



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



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



3. [[的行为相对地更接近于其他语言,例如"&&"而不是"-a"表示逻辑"与",用"||"而不是"-o"表示逻辑"或"。

例如:

$ [[ 1 < 2 && b > a ]]&&echo true||echo false

true

$ [[ 1 < 2 -a b > a ]]&&echo true||echo false

bash: syntax error in conditional expression

bash: syntax error near `-a'

$ [ 1 < 2 -a b > a ]&&echo true||echo false

true

$ [ 1 < 2 && b > a ]&&echo true||echo false #wrong syntax

bash: [: missing `]'

false

$ [ 1 < 2 \&\& b > a ]&&echo true||echo false #aslo wrong

bash: [: &&: binary operator expected

false





4. [ ... ]为shell命令,所以在其中的表达式应是它的命令行参数,所以串比较操作符">" 与"<"必须转义,否则就变成IO改向操作符了(请参看上面2中的例子)。在[[中"<"与">"不需转义;

由于"[["是关键字,不会做命令行扩展,因而相对的语法就稍严格些。例如

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

举例:

$ [ "-z" "" ]&&echo true||echo false

true

$ [ -z "" ]&&echo true||echo false

true

$ [[ "-z" "" ]]&&echo true||echo false

bash: conditional binary operator expected

bash: syntax error near `""'

$ [[ -z "" ]]&&echo true||echo false

true







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

举例:

$ [[ 99+1 -eq 100 ]]&&echo true||echo false

true

$ [ 99+1 -eq 100 ]&&echo true||echo false

bash: [: 99+1: integer expression expected

false

$ [ $((99+1)) -eq 100 ]&&echo true||echo false

true

----------
woodie 回复于:2005-12-26 16:21:11


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



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

举例:


$ ((i=1+99)) ; echo $i

100

$ echo $((i++))

101

$ echo $((--i))

100

$ echo $((2**3))

8

$ echo $((5%3))

2

$ echo $((1<2?10:20))

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


woodie 回复于:2005-12-26 16:24:36


>相比较而言,使用 [[ ]] 比使用 [ ] 更可靠,建议多多使用。

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



>不过woodie兄台所提到的第 4 点 是有些遗漏的,在 [ ]中若直接使用 > < 其结果会很迷惑的。

看来shaoping兄还是没搞清楚,大概是我前面都没写清楚吧。:)

"<"和">"可以直接用在[[]]中。但可以直接用在[]中,只能加"\"转义后或者用引号括起后使用,否则shell就会把它解释为输入输出改向符。

看例子:

$ ls 200?

ls: 200?: No such file or directory

$ [ 2004 < 2005 ]

bash: 2005: No such file or directory

$ echo $?

1

$ [ 2004 > 2005 ]

$ echo $?

0

$ ls 200?

2005





首先列一下目录,保证没有200?字样的文件存在。

然后执行[ 2004 < 2005 ],shell试图对文件2005作标准输入,但无法找到文件2005。

执行[ 2004 > 2005 ],系统正常执行了命令。

再列下目录,已经生成了文件2005!

再看:


$ [ 2004 "<" 2006 ]&&echo true||echo false

true

$ [ 2004 '>' 2006 ]&&echo true||echo false

false

$ [ 2004 \> 2006 ]&&echo true||echo false

false



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