条件表达式中 `==` 和 `=` 之间有什么区别?

Tim*_*Tim 5 bash

来自 bash 手册,用于条件表达式

string1 == string2
string1 = string2
Run Code Online (Sandbox Code Playgroud)

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

  1. 当与该[[命令一起使用时,它会执行上述模式匹配(参见第 3.2.4.2 节 [条件构造],第 10 页)。

    • “模式匹配”在这里是什么意思?

    • 什么是“模式匹配”?

    • 如果不[[与其他命令一起使用,但与其他命令一起使用,“this”执行什么?

  2. '=' 应该与testposix 一致性命令一起使用。

    • POSIX 在这里说什么?

    • 反对的句子是什么?

    • 可以==test命令一起使用吗?我试过了,似乎是的。

    • 可以=用除此之外其它命令中使用test?我试着=[[[,似乎是肯定的。

  3. ==和之间有什么区别=

    在bash 4.3,我试图===test[[[== 并且=看起来是一样的我。

    可以===在任何条件表达式互换使用?

谢谢。

ilk*_*chu 12

POSIX test( 或[ ... ]) 只知道有一个等号的那个:

s1 = s2
如果字符串 s1 和 s2 相同,则为真;否则为假。

但是 Bash 也接受双等号,尽管内置帮助不承认这一点(手册确实如此):

$ help test | grep =  -A1
  STRING1 = STRING2
                 True if the strings are equal.
  STRING1 != STRING2
                 True if the strings are not equal.
Run Code Online (Sandbox Code Playgroud)

至于其他贝壳,则视情况而定。好吧,尤其是 Dash 是这里的顽固者:

$ dash -c '[ x == x ] && echo foo'
dash: 1: [: x: unexpected operator
Run Code Online (Sandbox Code Playgroud)

$ yash -c '[ x == x ] && echo foo'
foo
$ busybox sh -c '[ x == x ] && echo foo'
foo
$ ksh93 -c '[ x == x ] && echo foo'
foo
Run Code Online (Sandbox Code Playgroud)

zsh这里有点奇怪,==被认为是一个特殊的运算符,所以它必须被引用:

$ zsh -c '[ x == x ] && echo foo'
zsh:1: = not found

$ zsh -c '[ x "==" x ] && echo foo'
foo
Run Code Online (Sandbox Code Playgroud)

我的 Debian 上的 GNU coreutils的 external test/[实用程序支持==(但手册不承认这一点),而 OS X 上的不支持。

因此,使用test/ [ .. ]=因为它得到了更广泛的支持。


使用[[ ... ]]构造,两者===都相等(至少在 Bash 中),并且运算符的右侧被视为一个模式,就像在文件名 glob 中一样,除非它被引用。(文件名不在 内扩展[[ ... ]]

$ bash -c '[[ xxx == x* ]] && echo foo'
foo
Run Code Online (Sandbox Code Playgroud)

但当然,这种结构不是标准的:

$ dash -c '[[ xxx == x* ]] && echo foo'
dash: 1: [[: not found
$ yash -c '[[ xx == x* ]] && echo foo'
yash: no such command ‘[[’
Run Code Online (Sandbox Code Playgroud)

虽然 Busybox 有它,但它不进行模式匹配:

$ busybox sh -c '[[ xx == xx ]] && echo yes || echo no'
yes
$ busybox sh -c '[[ xx == x* ]] && echo yes || echo no'
no
Run Code Online (Sandbox Code Playgroud)


小智 6

在 bash 中,关于相等有四个条件:

\n\n
    \n
  • =内部(或测试)的简单和最基本(并且仅 posix 兼容)[ \xe2\x80\xa6 ]
    \n仅执行两个字符串的相等(逐字节)。

    \n\n
    \n
     STRING1 = STRING2\n             True if the strings are equal.\n
    Run Code Online (Sandbox Code Playgroud)\n
  • \n
  • 扩展 ==. 它仍然(仅)执行相等测试。

    \n\n
    $ [ aaaa == aaaa ] && echo yes\nyes\n\n$ [ aaaa == a* ] && echo yes\n$\n
    Run Code Online (Sandbox Code Playgroud)\n\n

    请注意,a*如果密码中存在匹配的文件名,则未加引号的内容将扩展为一个(或多个)文件名。具体来说:名为 aaaa 的现有文件将使代码输出 yes。如果没有匹配的文件,则精确比较会受到 failedglob 和 nullglob shell 选项的影响。

  • \n
  • a=内的 A[[完全等同于:

  • \n
  • a==内部的 A[[既进行逐字节匹配,又进行全局匹配。

    \n\n

    如果右侧的字符串或变量==被引用,则进行字节比较。如果所有字节都相等,则结果为[[“好”(0)。

    \n\n

    如果字符串(或者在所有情况下最好是:变量)未加引号,则按照文件名 glob 中的方式执行匹配。

    \n\n
    $ [[ aaaa == "aaaa" ]] && echo yes\nyes\n\n$ a=\'aaaa\'\n$ [[ aaaa == "$a" ]] && echo yes\nyes\n\n$ a=\'a*\'\n$ [[ aaaa == "$a" ]] && echo yes\n$\n\n$ a=\'a*\'\n$ [[ aaaa == $a ]] && echo yes\nyes\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
\n\n

有趣的是,未引用的内容aaaa也有效:

\n\n
$ a=\'aaaa\'\n$ [[ aaaa = $a ]] && echo yes\nyes\n
Run Code Online (Sandbox Code Playgroud)\n\n

发生这种情况是因为变量内的字符串没有任何可扩展的全局字符*, +, ?,[以及扩展的(如果激活)|,@!。但这通常是一个冒险的选择。

\n