![shell 比较中单等号 (=) 和双等号 (=) 有什么区别?](https://linux22.com/image/30940/shell%20%E6%AF%94%E8%BE%83%E4%B8%AD%E5%8D%95%E7%AD%89%E5%8F%B7%20(%3D)%20%E5%92%8C%E5%8F%8C%E7%AD%89%E5%8F%B7%20(%3D)%20%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%EF%BC%9F.png)
请阅读,为了比较内部的字符串,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
或$b
等expr
运算符的值也会失败(
,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 和,但请注意,ksh
bash
yash
ash
zsh
zsh
=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
答案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(在 外部[[…]]
)中也失败。