如何在Bash中比较数字?

我无法获得数字比较工作:

echo "enter two numbers";read a b;
echo "a=$a";echo "b=$b";
if [ $a \> $b ];thenecho "a is greater than b";elseecho "b is greater than a";fi;

问题是它比较了从第一个数字开始的数字,即9大于10,但1大于09。

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

1354123 次浏览

在Bash中,您应该在算术上下文中进行检查:

if (( a > b )); then...fi

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

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

您可以获得带有help testman test的比较运算符的完整列表。

在Bash中,我更喜欢这样做,因为它更多地将自己定位为条件操作,而不是使用(( )),后者更具算术性。

[[ n -gt m ]]

除非我做一些复杂的事情

(( (n + 1) > m ))

但每个人都有自己的喜好。可悲的是,有些人把他们的非官方标准强加于人。

你也可以这样做:

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

它允许您添加除算术之外可以用[[ ]]做的其他事情。

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

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

这段代码将打印ab中最小的数字

此代码也可以比较浮点数。它使用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 $?

要使其使用更短,请使用此功能:

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=$1op=$2num2=$3E_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; fiif ! [[ $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 falsetrue$ compare_nums -1.2345 ">=" 23 && echo true || echo falsefalse

像这样:

#!/bin/bash
a=2462620b=2462620
if [ "$a" -eq "$b" ]; thenecho "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}

这里有两个重要的假设:

  1. 输入是“正常SemVer字符串
  2. 每个部分在0-999之间

例如

versionToInt 12.34.56  # --> 12034056versionToInt 1.2.3     # -->  1002003

示例测试npm命令是否满足最低要求…

NPM_ACTUAL=$(versionToInt $(npm --version))  # Capture npm versionNPM_REQUIRED=$(versionToInt 4.3.0)           # Desired versionif [ $NPM_ACTUAL \< $NPM_REQUIRED ]; thenecho "Please update to npm@latest"exit 1fi

如果你有浮点数,你可以编写一个函数,然后使用它。例如,

#!/bin/bash
function float_gt() {perl -e "{if($1>$2){print 1} else {print 0}}"}
x=3.14y=5.20if [ $(float_gt $x $y) == 1 ] ; thenecho "do stuff with x"elseecho "do stuff with y"fi

如果您还想使用浮点数,括号(例如[[ $a -gt $b ]](( $a > $b )))是不够的;它会报告语法错误。如果您想将浮点数或浮点数与整数进行比较,您可以使用(( $(bc <<< "...") ))

例如,

a=2.00b=1
if (( $(bc <<<"$a > $b") )); thenecho "a is greater than b"elseecho "a is not greater than b"fi

您可以在if语句中包含多个比较。例如,

a=2.b=1c=1.0000
if (( $(bc <<<"$b == $c && $b < $a") )); thenecho "b is equal to c but less than a"elseecho "b is either not equal to c and/or not less than a"fi

如果您想检查数字变量(整数或非整数)是否在数字范围内,这很有帮助。

单线解决方案。

a=2b=1[[ ${a} -gt ${b} ]] && echo "true" || echo "false"

gt参考:https://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html

&&引用:https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html

[[…]]构造引用:https://www.gnu.org/software/bash/manual/bash.html#index-_005b_005b

${}参考:https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02(2.6.2)

参数展开的格式如下:

${表达式}

其中表达式由所有字符组成,直到匹配的'}'。任何由a或在引用字符串中转义的'}',以及嵌入式算术扩展中的字符、命令替换、和可变展开,在确定匹配 '}'.

参数扩展的最简单形式是:

参数名

再加上以上所有的答案:

如果你在一个if语句中有多个表达式,你可以这样做:

if (( $a % 2 == 0 )) && (( $b % 2 != 0));thenecho "What you want to do"fi

希望这有帮助!