为什么 zsh 和 bash 中 `[ ... ]` 中 `==` 的行为不同?

为什么 zsh 和 bash 中 `[ ... ]` 中 `==` 的行为不同?

我在这样做时得到了我的预期bash

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

它给了我yes

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

zsh: = not found

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

答案1

它不在/usr/bin/[任何一个壳中。在 Bash 中,您使用的是内置test/[命令, 和类似地在 zsh 中

不同之处在于zsh也有一个=扩展:=foo扩展为可执行文件的路径foo。这意味着==被视为试图找到=您的命令中调用的命令PATH。由于该命令不存在,因此您会收到错误

zsh: = not found

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


==如果您确实需要,请使用此处。这正如您在 zsh 中所期望的那样工作:

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

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


但是,您最好这样做:

  • 使用单=, POSIX 兼容的相等性测试;或者
  • 更好的是,使用[[条件句与==同时重击桀骜。一般来说,[[更好、更安全,包括通过内部特殊的解析规则来避免此类问题(和其他问题)。

答案2

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

$ type [
[ is a shell builtin

来自Shell 内置命令文档:

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

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

字符串 1 = 字符串 2

如果字符串相等则为 True。

所以,正确的表达是:

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

发生的情况是 bash 不太严格。支持==运营商[ 似乎是 bash 扩展并且不建议使用它:

字符串1 == 字符串2

字符串1 = 字符串2

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

'=' 应与测试命令一起使用以确保 POSIX 一致性。

如果你想使用==,你应该使用[[关键字:

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

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

答案3

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

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

答案4

在 和 两个 shell 中bashzsh[实用程序是 shell 内置程序。这是该工具的 shell 实现,它优先于二进制/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 测试实用程序规范没有==定义运算符。

相关内容