条件表达式中的“==”和“=”有什么区别?

条件表达式中的“==”和“=”有什么区别?

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

string1 == string2
string1 = string2

如果字符串相等则为 True。

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

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

    • 这里的“模式匹配”与什么相对?

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

  2. '=' 应与命令一起使用test以保持 posix 一致性。

    • POSIX 这里说了什么?

    • 反对的句子是什么?

    • 可以==test命令吗?我试过了,看来是的。

    • 除此以外还能=和其他命令一起使用吗test?我尝试了和=,似乎可以。[[[

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

    在 Bash 4.3 中,我尝试将===test, [[, 和一起使用[。在我看来===一样的。

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

谢谢。

答案1

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

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.

至于其他的贝壳,就看情况了。嗯,尤其是 Dash 是这里最顽固的一个:

$ dash -c '[ x == x ] && echo foo'
dash: 1: [: x: unexpected operator

$ yash -c '[ x == x ] && echo foo'
foo
$ busybox sh -c '[ x == x ] && echo foo'
foo
$ ksh93 -c '[ x == x ] && echo foo'
foo

zsh=something是一个文件名扩展something运算符,如果在中找到,则扩展为命令的路径,除非关闭$PATH该选项(例如模拟其他 shell 时),并且也适用于或在简单命令的参数中找到时,例如,至少必须引用前导那里:equals===~test[=

$ zsh -c 'echo =ls'
/usr/bin/ls

$ zsh +o equals -c 'echo =ls'
=ls

$ zsh --emulate ksh -c 'echo =ls'
=ls

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

$ zsh -c '[ x "==" x ] && echo foo'
foo

我的 Debian 上的 GNU coreutils 的外部test/实用程序支持(但是[==手动的不承认这一点),而 OS X 上的则不然。

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


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

$ bash -c '[[ xxx == x* ]] && echo foo'
foo

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

$ dash -c '[[ xxx == x* ]] && echo foo'
dash: 1: [[: not found
$ yash -c '[[ xx == x* ]] && echo foo'
yash: no such command ‘[[’

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

$ busybox sh -c '[[ xx == xx ]] && echo yes || echo no'
yes
$ busybox sh -c '[[ xx == x* ]] && echo yes || echo no'
no

答案2

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

  • =内部(或测试)简单且最基本(且仅与 posix 兼容)[ … ]
    仅执行两个字符串的相等(逐字节)。

     STRING1 = STRING2
                 True if the strings are equal.
    
  • 扩展 ==。它仍然(仅)执行相等测试。

    $ [ aaaa == aaaa ] && echo yes
    yes
    
    $ [ aaaa == a* ] && echo yes
    $
    

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

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

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

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

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

    $ [[ aaaa == "aaaa" ]] && echo yes
    yes
    
    $ a='aaaa'
    $ [[ aaaa == "$a" ]] && echo yes
    yes
    
    $ a='a*'
    $ [[ aaaa == "$a" ]] && echo yes
    $
    
    $ a='a*'
    $ [[ aaaa == $a ]] && echo yes
    yes
    

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

$ a='aaaa'
$ [[ aaaa = $a ]] && echo yes
yes

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

相关内容