在bash中,"-ne"代表什么意思?

117

在bash脚本中,命令"-ne"是什么意思?

例如,下面的一行bash脚本代码是做什么用的?

[ $RESULT -ne 0 ] 

2
请查看http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html。 - Nemo
3
判断$RESULT的值是否"不等于"0。 - lurker
14
它是数字不平等;"!="表示字符串不相等。 - Keith Thompson
7
“在bash中”这并没有什么实际意义。[ 运行了一个名为 test 的命令。-netest 命令的参数,不是bash的参数。你可以在 man test 中找到有关 -ne 参数的文档说明。 - Charles Duffy
3
顺便提一下,这段代码有错误,因为你没有使用引号。最起码这应该是 [ "$RESULT" -ne 0 ] -- 或者更好的是 (( RESULT != 0 ))。(更好的做法是,如果你从 $? 中获取这个值,你可以直接在命令退出状态上进行分支,而不是运行命令,将其退出状态捕获到一个变量中,然后将该变量的值替换为一个 test 命令)。 - Charles Duffy
显示剩余8条评论
4个回答

154
这是一件如果你不知道在哪里寻找的事情可能会很难搜索的东西。[ 实际上是一个命令,而不是bash shell语法的一部分,尽管你可能期望它是。它恰好是一个Bash内置命令,因此在Bash手册中有记录。
还有一个外部命令也可以完成相同的工作,在许多系统上,它由GNU Coreutils软件包提供。 [ 等效于 test 命令,不同之处在于 [ 需要 ] 作为其最后一个参数,而 test 不需要。
假设bash文档已经安装在您的系统上,如果您键入 info bash 并搜索 'test''['(单引号是搜索的一部分),您将找到关于命令 [,也称为 test 命令的文档。如果您使用的是 man bash 而不是 info bash,请搜索 ^ *test(在某些空格后跟随一行开头的单词 test)。
跟随“Bash条件表达式”的引用将带您进入 -ne 的描述,这是数字不等运算符("ne"代表"not equal")。相比之下,!=是字符串不等运算符。
您也可以在Web上找到bash文档。
  • Bash 条件表达式 -- (向下滚动;-ne 在 "arg1 OP arg2" 下面)
  • test 的 POSIX 文档
  • test 命令的官方定义是 POSIX 标准(bash 实现应该合理地符合该标准,但可能具有某些扩展功能)。


    我倾向于建议使用POSIX文档而不是coreutils文档。毕竟,“test”是一个POSIX命令。 - Charles Duffy

    87

    "不相等" 在这种情况下,$RESULT 被测试为不等于零。

    然而,这个测试是以数字方式进行的,而不是按字母顺序进行的:

    n1 -ne n2     True if the integers n1 and n2 are not algebraically equal.
    

    相对于:

    s1 != s2      True if the strings s1 and s2 are not identical.
    

    5
    指出数字和字符串比较的差异是一个很好的观点...这很容易被忽视。 - dreftymac

    5

    为之前的答案增添额外背景。

    自从我umpteen年前开始在BaSH编程以来,我仍然发现数学运算符的主题很难记住。由于其许多怪癖,BaSH经常让人沮丧。一个经典的例子是编写包含整数的变量的等于/不等于比较,因为它需要完全不同的技术,与其他基本操作数(如小于、大于等)相比。处理这些其他操作数的一些典型方法(例如((..)))不能正确地应用于等于/不等于公式。

    针对OP的问题,让我们看一些如何尝试在BaSH中将两个整数进行数字比较的示例,并使用示例来帮助澄清哪些方法可行,哪些不可行。我只会限制我的评论在等于/不等于逻辑上。

    谈论这个话题时不能没有提到基本数系统。 BaSH文档通常很不清晰。例如,在某些情况下,BaSH假定整数是八进制(8进制),而大多数人假定是十进制(10进制)。编写具有数字比较的脚本时,很容易不注意到您正在创建问题,直到将来某个时候调试它以查看意外结果。虽然BaSH的行为有时似乎不一致,但实际上只是完全理解BaSH如何解释字符串和数字的问题。

    比较整数不使用前导零。

    当您确信要比较的整数绝对不会带有前导零时,您可以使用以下任何一种方法:

    #/bin/bash
    a=4
    b=4
    printf "method 1: "; if [ $a != $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 2: "; if [ "$a" != "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 3: "; if [ $a -ne $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 4: "; if [ "$a" -ne "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 5: "; if (( a != b )); then printf "not equal"; else printf "equal"; fi; printf "\n"
    

    比较带前导零的整数。

    现在,假设您将或可能拥有至少一个带前导零的变量。如果是这种情况,则某些方法将无法正确工作(会生成错误或返回错误结果)。这是因为BaSH将数值解释为字符串并将两个数字作为字符串进行比较,或者因为BaSH期望这些值为8进制整数,并遇到了无法在八进制数字系统下解释的字符。

    有各种方法可以解决这些问题,但最简单的方法是不使用某些用于比较整数的技巧。


    当您尝试比较实际值时,这些方法不起作用。它们将错误地返回“不相等”的结果。当然,如果您确实希望比较字面字符串,则这可能是一种理想的结果,因此它真的取决于您的用例。无论如何,重点是这些公式将“x”与“0x”视为不相等,即使对于人类来说它们是相同的数值。

    看一些例子:

    整数,没有前导零。任何这些公式都适用。

    #!/bin/bash
    a=7
    b=7
    printf "method 1: "; if [ $a != $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 2: "; if [ "$a" != "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 3: "; if [ $a -ne $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 4: "; if [ "$a" -ne "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 5: "; if (( a != b )); then printf "not equal"; else printf "equal"; fi; printf "\n"
    
    Output:
    method 1: equal
    method 2: equal
    method 3: equal
    method 4: equal
    method 5: equal
    

    同样的问题,看起来没问题(但实际上是有问题的):
    #!/bin/bash
    a=7
    b=8
    printf "method 1: "; if [ $a != $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 2: "; if [ "$a" != "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 3: "; if [ $a -ne $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 4: "; if [ "$a" -ne "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 5: "; if (( a != b )); then printf "not equal"; else printf "equal"; fi; printf "\n"
    
    Output:
    method 1: not equal
    method 2: not equal
    method 3: not equal
    method 4: not equal
    method 5: not equal
    

    当引入前导零时,问题就会开始出现。

    在IT技术中,前导零可能会影响数字的解析和计算结果。
    #!/bin/bash
    a=04
    b=4
    printf "method 1: "; if [ $a != $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 2: "; if [ "$a" != "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 3: "; if [ $a -ne $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 4: "; if [ "$a" -ne "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 5: "; if (( a != b )); then printf "not equal"; else printf "equal"; fi; printf "\n"
    
    Output:
    method 1: not equal
    method 2: not equal
    method 3: equal
    method 4: equal
    method 5: equal
    

    在上面的例子中,输出结果是不一致的。这是因为前两种方法将$a和$b作为字符串进行比较,意味着它们的内容是逐字比较的。与此同时,第三到第五种方法将$a和$b转换为数字,然后进行比较,所以这些方法似乎可以正常工作。然而,还有另一个值得注意的问题。
    通常应避免使用第五种方法。
    #!/bin/bash
    a=8
    b=08
    printf "method 1: "; if [ $a != $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 2: "; if [ "$a" != "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 3: "; if [ $a -ne $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 4: "; if [ "$a" -ne "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 5: "; if (( a != b )); then printf "not equal"; else printf "equal"; fi; printf "\n"
    
    Output:
    method 1: not equal
    method 2: not equal
    method 3: equal
    method 4: equal
    method 5: main.sh: line 8: ((: 08: value too great for base (error token is "08")
    equal
    

    如上所示,前两种方法返回FALSE(不相等)的比较结果,因为它们将两个值作为字符串进行比较。更重要的是,第五种方法会生成错误,因为BaSH希望八进制数,并且不知道在以零开头的非零值时该怎么做。使用此方法的另一个挑战是,即使您抑制了错误消息,它每次都返回FALSE结果,而不管是否正确,如下所示。

    #!/bin/bash
    a=8
    b=09
    printf "method 1: "; if [ $a != $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 2: "; if [ "$a" != "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 3: "; if [ $a -ne $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 4: "; if [ "$a" -ne "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 5: "; if (( a != b )); then printf "not equal"; else printf "equal"; fi; printf "\n"
    
    Output:
    method 1: not equal
    method 2: not equal
    method 3: not equal
    method 4: not equal
    method 5: main.sh: line 8: ((: 09: value too great for base (error token is "09")
    equal
    

    值得一提的是,第五种方法的这个变化也表现不佳:
    printf "method 5: "; if (( $a != $b )); then printf "not equal"; else printf "equal"; fi; printf "\n"
    

    也不是这样的:

    printf "method 5: "; if (( "$a" != "$b" )); then printf "not equal"; else printf "equal"; fi; printf "\n"
    

    结论

    总的来说,在BaSH中比较两个整数时,应该使用这种类型的公式表达式,而不是其他提到的表达式。这假设您的用例涉及使用等于或不等于运算符将两个10进制整数相互比较。

    printf "method 3: "; if [ $a -ne $b ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    printf "method 4: "; if [ "$a" -ne "$b" ]; then printf "not equal"; else printf "equal"; fi; printf "\n"
    

    比较整数是否相等也遵循同样的逻辑。
    printf "method 3: "; if [ $a -eq $b ]; then printf "equal"; else printf "not equal"; fi; printf "\n"
    printf "method 4: "; if [ "$a" -eq "$b" ]; then printf "equal"; else printf "not equal"; fi; printf "\n"
    

    0
    -ne用于比较两个整数是否不相等。
    [[ "$numberA" -ne "$numberB" ]]
    

    !=比较两个字符串是否不相等:

    [[ "$stringA" -ne "$stringB" ]]
    

    为什么会同时存在两种情况呢?即使两个数字不相等,它们也可能是相同的字符串。
    这是因为比较数字的速度更快。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接