shell 比较中单等号 (=) 和双等号 (=) 有什么区别?

shell 比较中单等号 (=) 和双等号 (=) 有什么区别?

请阅读,为了比较内部的字符串,if我们需要使用双方括号。有的书上说可以通过 来进行比较=。但它==也适用于。

#!/bin/bash
a="hello"
b="world"
if [[ $a == $b ]];then
    echo "equal"
fi

===比较有区别吗?

答案1

bash(就像从ksh哪里bash复制该语法一样),[[ $a == $b ]]不是比较,而是模式匹配。您需要[[ $a == "$b" ]]进行字节到字节的相等比较。===任何支持[[...]].

[[...]]不是标准sh语法。这[ 命令是标准,并且标准比较存在运算符=(尽管某些[实现也可以识别==1)。

就像任何命令的任何参数一样,必须引用变量扩展以防止分割+全局和空删除(仅后者在 中执行zsh),所以:

[ "$a" = "$b" ]

在标准中sh,模式匹配是通过以下方式完成的case

case $a in
  ($b) ...
esac

为了完整起见,其他类似平等的您可能在 shell 脚本中遇到的运算符:

  • [ "$a" -eq "$b" ][比较十进制整数的标准运算符。有些[实现允许数字周围有空格,有些允许任意算术表达式,但这不可移植。可移植地,人们可以使用[ "$(($a))" -eq "$(($b))" ]它。另请参阅[ "$((a == b))" -ne 0 ]以下标准等效项(POSIXly 除外,仅当$a$b包含整数常量时才指定行为):

  • ((a == b)),来自 ksh ,也可在zsh和中找到bash,如果 中存储的算术表达式的计算结果$a与 的结果相同,则返回 true $b。通常,它用于比较数字。请注意,shell 之间在如何计算算术表达式以及支持哪些数字方面存在差异(例如 bash 和 ksh 的某些实现/版本不支持浮点或将带前导零的数字视为八进制)。

  • expr "$a" = "$b"如果两个操作数都被识别为十进制整数(有些允许数字周围有空格),则进行数字比较,否则检查两个字符串操作数是否具有相同的排序顺序。对于$a$bexpr运算符的值也会失败(substr...

  • awk -- 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b":如果$a$b被识别为数字(至少是十进制整数和浮点数,如 1.2、-1.5e-4,忽略前导尾随空格,有些还识别十六进制、八进制或 识别的任何数字strtod()),则执行数字比较。否则,根据实现的不同,它要么是字节到字节的字符串比较,要么是类似的expr比较strcoll(),即$a$b排序是否相同。

也可以看看:


1 包括 GNU[和, ,[的内置函数,虽然不是全部基于 shell 和,但请注意,kshbashyashashzshzsh=cmd是一个特殊的文件名扩展运算符(在相同的上下文中扩展~user)扩展为相应命令的路径,因此,除非您关闭equals禁用该功能的选项,否则您需要编写它[ "$a" '==' "$b" ],否则您会收到一个错误,该=命令没有找到。同样适用于[ "$string" '=~' "$regexp" ]

答案2

这些在 bash 中是等效的:

[[ $x == "$y" ]]
[[ $x = "$y" ]]
[ "$x" == "$y" ]
[ "$x" = "$y" ]

前两个 $x 变量不必加引号。 Bash 在 [ 内执行分词和路径名扩展,但不在 [[ 内执行:

$ x='a b'
$ [ -s $x ]
-bash: [: a: binary operator expected
$ [[ -s $x ]]
$ ls
$ [ a = * ]
-bash: [: a: unary operator expected
$ [[ a = * ]]
$ 

[[ $x = "$y" ]]是字符串比较,但是[[ $x = $y ]]是模式匹配表达式:

$ y='a*'; [[ aa = "$y" ]]; echo $?
1
$ y='a*'; [[ aa = $y ]]; echo $?
0

-eq 仅适用于整数:

$ [[ x.x -eq x.x ]]
-bash: [[: x.x: syntax error: invalid arithmetic operator (error token is ".x")
$ x=9; [[ "x" -eq 9 ]]; echo $?
0

也可以看看BashFAQ/031:测试、[ 和 [[ 之间有什么区别?

答案3

=都是==运算符。在某些语言(如 C)中,一种用于为变量赋值,另一种用于比较值(算术表达式的结果)。事实上,这两个运算符正是算术求值中的运算符。 A$((a=23))是赋值,a$((a==23))是算术比较。

$ echo "$((a=11)) $((a==23))" "$((a=23))" "$((a==23))"
11 0 23 1

但在测试结构内部(所有测试[…][[…]]) 两个运算符的含义相同并执行相同的操作。

所以,所有这些选项:

test "$a" =  "$b"
   [ "$a" =  "$b" ]
  [[ "$a" =  "$b" ]]
test "$a" == "$b"
   [ "$a" == "$b" ]
  [[ "$a" == "$b" ]]

内部等效巴什测试二进制相等(引用的变量)。如果正确的变量未加引号,则它可能会被解释为模式并进行相应的匹配:作为模式而不是文字字符串。

带引号的运算符\=\==在 test 和 中使用时也是等效的[…]。但引用的运算符\==在内部失败[[…]]

对于其他 shell,结果各不相同(正确的结果应该是Y -(true false),不同于 0 (true) 和 1 (false) 的退出代码将报告为失败¤)。某些 shell 会失败- -(退出代码始终为 1)。

                     | dash  ksh   bash  zsh   
  test a  =  "$b"    | Y -   Y -   Y -   Y -    
     [ a  =  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a  =  "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a  == "$b"    | ¤ ¤   Y -   Y -   - -    
     [ a  == "$b" ]  | ¤ ¤   Y -   Y -   - -    
    [[ a  == "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a \=  "$b"    | Y -   Y -   Y -   Y -    
     [ a \=  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a \=  "$b" ]] | ¤ ¤   Y -   - -   - -    
  test a \== "$b"    | ¤ ¤   Y -   Y -   Y -    
     [ a \== "$b" ]  | ¤ ¤   Y -   Y -   Y -    
    [[ a \== "$b" ]] | ¤ ¤   Y -   - -   - -

所有选项都可以在 ksh 中使用,带引号的运算符在 bash 和 zsh(在 内部[[…]])中失败,而未加引号的运算\=\==在 zsh(在 外部[[…]])中也失败。

相关内容