Comparing numbers in Bash
我开始学习如何为bash终端编写脚本,但我无法解决如何使比较工作正常进行的问题。我使用的脚本是:
1 2 3 4 5 6 7 8 9 10 11 12 | echo"enter two numbers"; read a b; echo"a=$a"; echo"b=$b"; if [ $a \> $b ]; then echo"a is greater than b"; else echo"b is greater than a"; fi; |
我的问题是,它比较上第一个数字的数字,即9大于10000,1大于09
如何将数字转换为类型以进行真正的比较?
在bash中,您应该在算术上下文中执行检查:
1 2 3 | if (( a > b )); then ... fi |
对于不支持
1 2 3 | if ["$a" -gt"$b" ]; then ... fi |
您可以获得与
简单明了
1 2 3 4 5 6 7 8 | #!/bin/bash a=2462620 b=2462620 if ["$a" -eq"$b" ];then echo"They're equal"; fi |
如果您想在bash脚本编写的美妙世界中获得更多的数字对比,您可以查看这个作弊表。
很快,整数只能与以下项进行比较:
1 2 3 4 5 6 | -eq # equal -ne # not equal -lt # less than -le # less than or equal -gt # greater than -ge # greater than or equal |
还有一件事有些人可能不知道:
1 | echo $(( a < b ? a : b )) |
此代码将打印出
在bash中,我更喜欢这样做,因为它更倾向于将自己定位为一个条件操作,而不是使用更多是算术的
1 | [[ N -gt M ]] |
除非我做一些复杂的事情
1 | (( (N + 1) > M )) |
但每个人都有自己的偏好。可悲的是,有些人强加他们的非官方标准。
更新:
实际上,您也可以这样做:
1 | [[ 'N + 1' -gt M ]] |
它允许你添加一些你可以用
此代码还可以比较浮动。它使用的是awk(它不是纯bash),但是这不应该是问题,因为awk是一个标准的posix命令,很可能是默认情况下随操作系统提供的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $ 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 $? |
要缩短使用时间,请使用以下功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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 |
如果有浮点数,可以编写一个函数,然后使用它,例如
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/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 |
我通过使用一个小函数将版本字符串转换为可以比较的纯整数值来解决这个问题:
1 2 3 4 5 6 | function versionToInt() { local IFS=. parts=($1) let val=1000000*parts[0]+1000*parts[1]+parts[2] echo $val } |
这有两个重要的假设:
例如
1 2 | versionToInt 12.34.56 # --> 12034056 versionToInt 1.2.3 # --> 1002003 |
示例测试
1 2 3 4 5 6 | 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 |