带有 ((...)) 字符串比较的 if 语句在 bash 脚本中不起作用

带有 ((...)) 字符串比较的 if 语句在 bash 脚本中不起作用

我写了下面的脚本:

#!/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被视为模式。

另请参阅:Bash 运算符 [[ vs [ vs ( vs ((?

答案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

相关内容