如何在Bash中比较数字?

如何在Bash中比较数字?,bash,shell,numeric,Bash,Shell,Numeric,我无法进行数字比较: echo“输入两个数字”; 读a b; 回声“a=$a”; 回声“b=$b”; 如果[$a\>$b]; 然后 回声“a大于b”; 其他的 回声“b大于a”; fi; 问题是,它会比较从第一个数字开始的数字,即9大于10,但1大于09 如何将数字转换为类型以进行真正的比较?在Bash中,您应该在以下位置进行检查: 对于不支持(())的POSIX shell,可以使用-lt和-gt if [ "$a" -gt "$b" ]; then

我无法进行数字比较:

echo“输入两个数字”;
读a b;
回声“a=$a”;
回声“b=$b”;
如果[$a\>$b];
然后
回声“a大于b”;
其他的
回声“b大于a”;
fi;
问题是,它会比较从第一个数字开始的数字,即9大于10,但1大于09


如何将数字转换为类型以进行真正的比较?

在Bash中,您应该在以下位置进行检查:

对于不支持
(())
的POSIX shell,可以使用
-lt
-gt

if [ "$a" -gt "$b" ]; then
    ...
fi

在Bash中,您可以使用
帮助测试
人工测试
获得完整的比较运算符列表。我更喜欢这样做,因为它将自身更多地作为一个条件操作来处理,而不是使用更像算术的
(())

[[ n -gt m ]]
除非我做复杂的事情,比如

(( (n + 1) > m ))
但每个人都有自己的偏好。可悲的是,有些人强加了他们的非官方标准

您也可以这样做:

[[ 'n + 1' -gt m ]]

它允许您添加一些除了算术之外,还可以使用
[[]]
进行的其他操作。

还有一件好事有些人可能不知道:

echo $(( a < b ? a : b ))
echo$((a

此代码将打印
a
b

中的最小数字。此代码还可以比较浮动。它使用的是AWK(它不是纯Bash)。然而,这不应该是一个问题,因为AWK是一个标准POSIX命令,在默认情况下很可能随操作系统一起提供

$ awk 'BEGIN {return_code=(-1.2345 == -1.2345) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
0
$ awk 'BEGIN {return_code=(-1.2345 >= -1.2345) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
0
$ awk 'BEGIN {return_code=(-1.2345 < -1.2345) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
1
$ awk 'BEGIN {return_code=(-1.2345 < 2) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
0
$ awk 'BEGIN {return_code=(-1.2345 > 2) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
$awk'开始{return\u code=(-1.2345==-1.2345)?0:1;退出}结束{exit return\u code}
$echo$?
0
$awk'开始{return\u code=(-1.2345>=-1.2345)?0:1;退出}结束{exit return\u code}'
$echo$?
0
$awk'BEGIN{return\u code=(-1.2345<-1.2345)?0:1;exit}END{exit return\u code}
$echo$?
1.
$awk'BEGIN{return\u code=(-1.2345<2)?0:1;exit}END{exit return\u code}'
$echo$?
0
$awk'BEGIN{return\u code=(-1.2345>2)?0:1;exit}END{exit return\u code}'
$echo$?
要缩短使用时间,请使用此功能:

compare_nums()
{
   # Function to compare two numbers (float or integers) by using AWK.
   # The function will not print anything, but it will return 0 (if the comparison is true) or 1
   # (if the comparison is false) exit codes, so it can be used directly in shell one liners.
   #############
   ### Usage ###
   ### Note that you have to enclose the comparison operator in quotes.
   #############
   # compare_nums 1 ">" 2 # returns false
   # compare_nums 1.23 "<=" 2 # returns true
   # compare_nums -1.238 "<=" -2 # returns false
   #############################################
   num1=$1
   op=$2
   num2=$3
   E_BADARGS=65

   # Make sure that the provided numbers are actually numbers.
   if ! [[ $num1 =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then >&2 echo "$num1 is not a number"; return $E_BADARGS; fi
   if ! [[ $num2 =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then >&2 echo "$num2 is not a number"; return $E_BADARGS; fi

   # If you want to print the exit code as well (instead of only returning it), uncomment
   # the awk line below and comment the uncommented one which is two lines below.
   #awk 'BEGIN {print return_code=('$num1' '$op' '$num2') ? 0 : 1; exit} END {exit return_code}'
   awk 'BEGIN {return_code=('$num1' '$op' '$num2') ? 0 : 1; exit} END {exit return_code}'
   return_code=$?
   return $return_code
}

$ compare_nums -1.2345 ">=" -1.2345 && echo true || echo false
true
$ compare_nums -1.2345 ">=" 23 && echo true || echo false
false
比较 { #函数使用AWK比较两个数字(浮点或整数)。 #函数不会打印任何内容,但会返回0(如果比较为真)或1 #(如果比较为假)退出代码,因此可以直接在shell one衬里中使用。 ############# ###用法### ###请注意,必须将比较运算符括在引号中。 ############# #比较_nums1“>”2#返回false #比较_nums1.23“=”-1.2345&&echo true | | echo false 真的 $compare_nums-1.2345“>=”23&&echo true | | echo false 假的
像这样:

#!/bin/bash

a=2462620
b=2462620

if [ "$a" -eq "$b" ]; then
  echo "They're equal";
fi
整数可以与以下运算符进行比较:

-eq # Equal
-ne # Not equal
-lt # Less than
-le # Less than or equal
-gt # Greater than
-ge # Greater than or equal

请参阅。

我通过使用一个小函数将版本字符串转换为可比较的纯整数值来解决此问题:

function versionToInt() {
  local IFS=.
  parts=($1)
  let val=1000000*parts[0]+1000*parts[1]+parts[2]
  echo $val
}
这就产生了两个重要的假设:

  • 输入是一个“”
  • 每个部分都在0-999之间
  • 比如说

    versionToInt 12.34.56  # --> 12034056
    versionToInt 1.2.3     # -->  1002003
    
    示例测试
    npm
    命令是否满足最低要求

    NPM_ACTUAL=$(versionToInt $(npm --version))  # Capture npm version
    NPM_REQUIRED=$(versionToInt 4.3.0)           # Desired version
    if [ $NPM_ACTUAL \< $NPM_REQUIRED ]; then
      echo "Please update to npm@latest"
      exit 1
    fi
    
    NPM_实际=$(versionPoint$(NPM--version))#捕获NPM版本
    NPM_必需=$(VersionPoint 4.3.0)#所需版本
    如果[$NPM_实际\<$NPM_需要];则
    echo“请更新到npm@latest"
    出口1
    fi
    
    如果您有浮点数,您可以编写一个函数,然后使用它。例如

    #!/bin/bash
    
    function float_gt() {
        perl -e "{if($1>$2){print 1} else {print 0}}"
    }
    
    x=3.14
    y=5.20
    if [ $(float_gt $x $y) == 1 ] ; then
        echo "do stuff with x"
    else
        echo "do stuff with y"
    fi
    
    a=2.00
    b=1
    
    if (( $(bc <<<"$a > $b") )); then 
        echo "a is greater than b"
    else
        echo "a is not greater than b"
    fi
    
    a=2.
    b=1
    c=1.0000
    
    if (( $(bc <<<"$b == $c && $b < $a") )); then 
        echo "b is equal to c but less than a"
    else
        echo "b is either not equal to c and/or not less than a"
    fi
    

    如果您还想使用浮点数,括号(例如,
    [[$a-gt$b]]
    ($a>$b))
    )不够;它会报告语法错误。如果您想将浮点数或浮点数与整数进行比较,可以使用
    (($(bc基础阅读:顺便说一句,在bash中分号是一个语句分隔符,而不是一个语句终止符,这是一个新行。因此,如果一行上只有一条语句,那么在行尾的
    是多余的。没有任何危害,只是浪费击键(除非你喜欢键入分号)。强制将前导零的数字转换为小数:
    10#$number
    so
    number=09;echo“$((10#$number))”
    将输出
    9
    ,而
    echo$((number))
    将产生一个“值太大而不能用于基数”错误。答案都会告诉您什么是对的,但不会告诉您什么是错的:
    操作符在
    [
    命令用于比较两个字符串的排序顺序,而不是它们作为数字进行排序的顺序。您可以在
    man test
    中找到更多信息。这不是真的。如果
    a==b
    @konsolebox,它也会打印
    b
    。@konsolebox是我,还是5和5中最小的数字是5?您的陈述是不明确的。甚至应用这样的命令是不行的:
    echo“较小的数字是$((a
    他所说的是,如果
    a==b
    ,那么
    a
    仍然是真的。我不知道Bash的条件的所有变幻莫测之处,但几乎可以肯定的是,在某些情况下,这会产生不同。@bikemule不,他不是这么说的。如果
    a==b
    ,那么
    a
    的计算结果会是假的,这就是为什么会这样打印
    b
    。正如@jordanm
    “$a”-gt“$b”所说
    是正确的答案。下面是一个很好的测试操作符列表:。@advert2013你不应该在数字前面加零。零前缀数字在bashAh中是八进制的,好吧,这就解决了这个谜-我对零前缀数字没有任何用处,但知道错误来自何处很好注意
    test
    也是一个程序是
    [
    。因此
    帮助测试
    提供了相关信息。要了解内置(
    [[/code>和
    )是什么,您应该使用
    帮助bash
    并导航到该部分。算术表达式很棒,但操作数被视为。我刚刚解开了您的另一个更改-
    “$a”周围的双引号
    “$b”
    不是绝对必要的,但它们是必要的
    a=2.
    b=1
    c=1.0000
    
    if (( $(bc <<<"$b == $c && $b < $a") )); then 
        echo "b is equal to c but less than a"
    else
        echo "b is either not equal to c and/or not less than a"
    fi