为什么`==`在zsh和bash中的[[…]`内部表现不同?


9

在执行此操作时,我得到了期望的结果bash

[ "a" == "a" ] && echo yes

它给了我yes

但是当我在中执行此操作时zsh,我得到以下信息:

zsh: = not found

为什么同一命令(/usr/bin/[)在不同的Shell中表现不同?


5
它不是同一命令- $PATH搜索之前找到的内置函数。并且==不是有效的test语法/usr/bin/[。只要=是好的。
mikeserv '16

Answers:


18

它不在/usr/bin/[两个外壳中。在Bash中,您使用的是内置的test/ [命令在zsh中也是如此

区别在于zsh也具有=扩展名=foo扩展到foo可执行文件的路径。这意味着==被视为试图查找=您的中调用的命令PATH。由于该命令不存在,您会收到错误消息

zsh: = not found

您所看到的(实际上,即使您实际上正在使用,也会发生同样的事情/usr/bin/[)。


可以使用==在这里,如果你真正想要的。这可以在zsh中按预期工作:

[ "a" "==" "a" ] && echo yes

因为引用阻止=word扩展运行。您也可以使用禁用该equals选项setopt noequals


但是,您最好要么:

  • 使用单=,POSIX兼容的相等性测试 ; 要么
  • 更好的是,在Bashzsh中都使用带[[条件的==。总的来说,这是更好,更安全的方法,包括通过内部使用特殊的解析规则来避免此类问题(以及其他问题)。[[

[和之间的确切区别是[[什么?(在Google上搜索仅[ vs [[会给我结果vs,哈哈)
Johnson Steward

2
[[在这两种情况下都支持更广泛的测试,并且具有自定义的解析规则,从而避免了引用变量,运算符等问题。如果您专门使用Bash或zsh,请使用[[。如果要编写可移植脚本,请写入POSIX兼容的[/ test命令(在您的运行系统上,它可能是真实的命令,也可能不是真实的命令)。
Michael Homer

1
只是在[[那里使用而忘记[存在。
Michael Homer

1
你知道的...我不同意你的建议。[[能力不同。尝试使用:for f in *; do [ -e "$f" ] && for a in f d h p S b c; do [ "-$a" "$f" ] && for p in r w x u g; do [ "-$p" "$f" ] || p=-; a=$a$p; done && break; done && printf "%s:\t%s\n" "$a" "$f"; done
mikeserv '16

3
好了,=/ ==可以说是其中一个的情况下[[也不好过[,因为[[ a == b ]]做“一”匹配“b”的模式,而不是为“a”等于“B”为你所期望的。这意味着您需要编写[[ $a == "$b" ]]示例。至少,使用该[命令,如果您知道命令解析的工作原理,就知道需要[ "$a" = "$b" ]像其他命令一样编写它以防止split + glob运算符。考虑到这一点,如果您不使用-a或-o,[则在符合POSIX的实现中是安全的。
斯特凡Chazelas

2

而zsh和bash给出了相同的答案(type两个shell也是内置的):

$ type -a [
[ is a shell builtin
[ is /usr/bin/[

2

[ 是bash和zsh中的shell内置命令:

$ type [
[ is a shell builtin

Shell Builtin Commands文档中

内置命令包含在外壳本身内。当将内置命令的名称用作简单命令的第一个单词时(请参见Simple Commands),shell将直接执行该命令,而无需调用其他程序。内置命令对于实现使用单独的实用工具无法获得或不方便的功能是必需的。

官方文档($ help test)仅允许使用=

STRING1 = STRING2

如果字符串相等,则为真。

因此,正确的表达式将是:

$ [ "a" = "a" ] && echo yes
yes

发生的是bash不太严格。支持==操作员[ 似乎是bash扩展,不建议使用它:

字符串1 ==字符串2

字符串1 =字符串2

如果字符串相等,则为真。当与[[命令一起使用时,它将执行如上所述的模式匹配(请参阅条件构造)。

测试命令必须使用'='来实现POSIX一致性。

如果要使用==,则应使用[[关键字:

$ [[ "a" == "a" ]] && echo yes
yes

请记住,[[它的便携性较差(不是POSIX)。但是bash和zsh都支持它。


1

在这两个壳,bash以及zsh,该[实用程序是一个shell内建命令。这是该工具的shell实现,它优先于binary使用/usr/bin/[。您遇到的不同结果是由不同的实现引起的。


在中bash[实用程序接受CONDITIONAL EXPRESSIONS[[复合命令。据bashs手册页都===有效:

string1 == string2
string1 = string2
        True if the strings are equal.  = should be used with the test command for POSIX
        conformance.

在中zsh,该[实用程序尝试在指定了POSIX及其扩展的地方实现它们。在POSIX测试实用程序规范中,没有==定义运算符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.