我写了下面的脚本:
#!/usr/bin/bash
STR_1="nfosys"
STR_2="Infosys"
if (( $STR_1 == $STR_2 ))
then
echo "Strings are equal"
else
echo "Strings are not equal"
fi
获取输出:
root:~/Desktop/user_repo/Demo# bash -x test.sh
+ STR_1=nfosys
+ STR_2=Infosys
+ (( nfosys == Infosys ))
+ echo 'Strings are equal'
Strings are equal
root:~/Desktop/user_repo/Demo#
理想情况下,它应该打印“字符串不相等”语句,但我无法理解为什么它打印“字符串相等”
答案1
(( .. ))
是一个算术构造,在算术上下文中,字符串被视为变量的名称,并使用该变量的值。这种情况发生在$var
扩展扩展之后,因此您的脚本会查看名为nfosys
和 的变量Infosys
。如果两个变量均未设置,则两者均为零,即相等。但:
$ str1=foo str2=bar foo=1
$ (( $str1 == $str2 )) && echo true || echo false
false
参见例如Bash 的 shell 算术手册:
允许 Shell 变量作为操作数;参数扩展在表达式求值之前执行。在表达式中,shell 变量也可以通过名称引用,而不使用参数扩展语法。当通过名称引用而不使用参数扩展语法时,为 null 或未设置的 shell 变量的计算结果为 0。
对于字符串比较,请使用
[ "$STR_1" = "$STR_2" ] # in any POSIX shell, or
[[ $STR_1 = "$STR_2" ]] # in Bash/ksh/zsh
前者由于分词需要引号,后者仅在右侧(在 bash / ksh 中)需要它,以免$STR_2
被视为模式。
答案2
相反,使用它[]
会产生想要的行为:
STR_1="nfosys"
STR_2="Infosys"
if [ $STR_1 = $STR_2 ]
then
echo "Strings are equal"
else
echo "Strings are not equal"
fi
输出:
+ STR_1=nfosys
+ STR_2=Infosys
+ '[' nfosys = Infosys ']'
+ echo 'Strings are not equal'
Strings are not equal
一个好的经验法则是也引用你的变量,以防它们最终被错误解释或被扩展/分割:
STR_1="nfosys"
STR_2="Infosys"
if [ "$STR_1" = "$STR_2" ]
then
echo "Strings are equal"
else
echo "Strings are not equal"
fi
另外,虽然[]
被认为是 POSIX,但[[]]
如果您的主要目标是bash
, 则使用更好。
编者注:POSIX 只知道 single =
.
答案3
谢谢大家。我已重新启动会话并更改为单方括号 -
#!/usr/bin/bash
STR_1="nfosys"
STR_2="Infosys"
if [ $STR_1 == $STR_2 ]
then
echo "Strings are equal"
else
echo "Strings are not equal"
fi
如果我使用 sh test.sh 执行然后收到错误 -
root@ip:~# sh test.sh
test.sh: 6: [: nfosys: unexpected operator
Strings are not equal
root@ip:~# bash test.sh
Strings are not equal
如果我用 bash 执行然后显示正确的输出,没有任何错误
root@ip:~# bash test.sh
Strings are not equal
奇怪的是,在发布问题之前,我尝试了两种方法 - sh/bash 和 ()/[]。但重新启动会话后似乎工作正常。
编辑器刷新的代码遵循 POSIX,以及一些好的代码(小写变量名称、错误打印到 stderr、修复的主要==
问题等):
#!/bin/sh
str_1=nfosys
str_2=Infosys
if [ "$str_1" = "$str_2" ]; then
echo "Strings are equal"
else
echo "Strings are not equal" >&2
exit 1
fi