【问题标题】:Check whether one number equals another number in Bash检查一个数字是否等于 Bash 中的另一个数字
【发布时间】:2013-04-07 21:06:33
【问题描述】:

我一直在尝试比较 Bash 中的两个数字是否相等(如果相等则打印一条消息),但是对于这个简单的程序,我收到了一些奇怪的错误消息:

#!/bin/bash

fun2 (){
    $x = 3
    //#prog.sh: line 4: =: command not found
    if [x == 3]
        then
    //#prog.sh: line 6: [x: command not found
            echo "It's 3!"
    fi
}
fun2

相应的错误显示在导致这些错误的行下方。

【问题讨论】:

  • 我重新打开了,因为重复是关于与大于/小于比较的,这是关于平等的。

标签: bash


【解决方案1】:

一定是:

 if [ $x -eq 3 ]; then .....

如果您喜欢更易读和不言自明的代码,请使用以下语法:

 if test $x -eq 3; then .....

解释

要比较整数,您必须使用这些运算符(复制自 man test):

   INTEGER1 -eq INTEGER2
          INTEGER1 is equal to INTEGER2

   INTEGER1 -ge INTEGER2
          INTEGER1 is greater than or equal to INTEGER2

   INTEGER1 -gt INTEGER2
          INTEGER1 is greater than INTEGER2

   INTEGER1 -le INTEGER2
          INTEGER1 is less than or equal to INTEGER2

   INTEGER1 -lt INTEGER2
          INTEGER1 is less than INTEGER2

   INTEGER1 -ne INTEGER2
          INTEGER1 is not equal to INTEGER2

运算符 == 和 != 仅用于字符串比较。

有关信息:“[”命令是系统“测试”命令的别名。

【讨论】:

    【解决方案2】:

    Shell 脚本并不是真正意义上的完整语言,它在很大程度上依赖于其他外部命令才能工作。

    变量使用sigil,即它们前面的$。许多 shell 脚本语言使用变量符号来帮助区分字符串和变量。

    例如:

    foo=foo_value
    echo foo foo $foo foo
    

    将打印:

    foo foo foo_value foo
    

    请注意,字符串的 echo 语句不需要引号。 Windows Batch shell 非常相似:

    set foo = foo_value
    echo foo foo %foo% foo
    

    如您所见,sigil 是在应该扩展变量时使用的,而不是在您定义它时使用的。那是因为 Unix shell 是智能 shell。他们甚至在执行命令行之前就对它进行了修改。 shell 将替换环境变量之前执行:

    foo=bar
    $foo="whose value is this"  # Note the dollar sign!
    echo The value of foo is $foo
    echo The value of bar is $bar
    

    这将打印出来:

    The value of foo is foo
    The value of bar is whose value is this
    

    如果您使用set -xv 命令,您会看到$foo="whose value is this" 在执行之前扩展为bar=whose value is this"

    在像 KornShell 和 Bash 这样的 Bourne 风格的 shell 中,if 语句并不是你想象的那样。 if 命令执行语句,如果该命令返回零值,将选择 if 子句。例如:

    cat "foo" > my_file       # Create a one line file with the string foo in it.
    if grep -q "foo" my_file  # grep command will return a zero exit code if it finds foo
    then
        echo "The string 'foo' is in file my_file"
    fi
    

    请注意,if 子句 不是布尔语句。这是一个实际执行的命令。

    在 Unix 开发的早期,test 命令被创建。您可以进行人工测试,看看如何使用它。

    test 命令允许您这样做:

    foo=3
    bar=3
    if test foo -eq bar
    then
        echo "foo and bar are equal"
    else
        echo "foo and bar are not equal"
    fi
    

    如果你这样做:

    $ ls -li /bin/test /bin/[
    

    您将看到名为[ 的命令实际上存在,并且是test 命令的硬链接。这是为了让if 语句看起来更像是您将在常规编程语言中看到的 if 语句:

    foo=3
    bar=3
    if [ foo -eq bar ]
    then
        echo "foo and bar are equal"
    else
        echo "foo and bar are not equal"
    fi
    

    它与上面的脚本完全相同,但使用[ 而不是test

    这解释了为什么在许多测试中需要 破折号(它是 test 命令的参数,参数以破折号开头!)。它还解释了为什么在[] 周围需要空格。这些是实际的 Unix 命令,Unix 命令周围必须有空格,以便 shell 可以处理它们。

    另一个问题是:为什么 shell 对字符串和数字有两组不同的测试?那是因为字符串可能只包含数字,但不是真正的数字。例如,如果您进行库存,您可能有一个零件号00101。在数值上,它们是相等的,但作为字符串,它们是两个不同的字符串。 shell脚本无法知道。相反,您必须让 shell 脚本知道它是数字比较还是字符串比较。

    Perl 也有类似的问题,因为您没有将变量声明为数字或非数字:

                             Shell Script              Perl
    Boolean Operator     Numeric     String     Numeric    String
    ===================  =======     ======     =======    ======
    Equals                 -eq        =           ==         eq
    Not Equals             -ne        !=          !=         ne
    Greater Than           -gt        >           >          gt
    Less Than              -lt        <           <          lt
    Greater or Equals      -ge        >=          >=         ge
    Less Than or Equals    -le        <=          <=         le
    

    您可以尝试其他一些方法:

    $ echo "*"    # Echos the asterisk
    $ echo *      # No quotes: Prints all files in current directory
    

    在执行 echo 命令之前再次注意 shell 扩展 *。这是 shell 脚本和典型编程语言之间的主要区别。 Shell 在实际执行命令之前首先进行扩展(填充环境变量、glob 替换和运行子命令)。

    set -xv 将显示正在执行的命令,以及 shell 在执行前如何扩展命令。执行set +xv 将关闭它。尝试一下,您很快就会更好地理解 shell。

    【讨论】:

      【解决方案3】:

      对于第一条错误消息,删除美元符号 $ 并且等号 = 周围不允许有空格

      x=3
      

      对于第二条错误消息,在x 之前插入一个空格和一个美元符号$,在3 之后插入一个空格

      if [ $x -eq 3 ]
      

      作为loentar correctly pointed out,它必须是-eq,既不是=也不是==

      【讨论】:

        【解决方案4】:
        • [ ] 表达式中的空格是必需的,所以

          if [ $x == 3 ]; then

        • 您需要在 [ ] 测试中的变量上使用 sigill

        【讨论】:

          【解决方案5】:

          为清楚起见,使用== 表示相等而不是=,即使两者都有效。前者鼓励使用[[,后者可能与赋值混淆。使用(( … ))-lt-gt 进行数值比较。

          if [[ "${my_var}" == "val" ]]; then
            do_something
          fi
          
          if (( my_var == 3 )); then
            do_something
          fi
          
          if [[ "${my_var}" -gt 3 ]]; then
            do_something
          fi
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-10-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-09
            • 1970-01-01
            • 2016-04-14
            相关资源
            最近更新 更多