Сравнение чисел в Баш
Я начинаю узнавать о написании сценариев для терминала bash, но я не могу понять, как заставить сравнения работать правильно. Скрипт, который я использую:
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
Как я могу преобразовать числа в тип, чтобы сделать истинное сравнение?
7 ответов:
в bash, вы должны сделать вашей регистрации!--7-->арифметические контексте:
if (( a > b )); then ... fiдля оболочек POSIX, которые не поддерживают
(()), вы можете использовать-ltи-gt.if [ "$a" -gt "$b" ]; then ... fiвы можете получить полный список операторов сравнения с
help test.
легко и просто
#!/bin/bash a=2462620 b=2462620 if [ "$a" -eq "$b" ];then echo "They're equal"; fiВы можете ознакомиться эта шпаргалка если вы хотите больше сравнений чисел в прекрасном мире сценариев Bash.
Короче говоря, целые числа можно сравнить только с:
-eq # equal -ne # not equal -lt # less than -le # less than or equal -gt # greater than -ge # greater than or equal
есть также одна хорошая вещь, о которой некоторые люди могут не знать:
echo $(( a < b ? a : b ))этот код выведет наименьшее число из
aиb
в Bash я предпочитаю делать это, поскольку он обращается больше как условная операция в отличие от использования
(( ))что больше арифметики.[[ N -gt M ]]если я не делаю сложные вещи, как
(( (N + 1) > M ))но у каждого есть свои предпочтения. Печально, что некоторые люди навязывают свои неофициальные стандарты.
обновление:
вы на самом деле можете также сделать это:
[[ 'N + 1' -gt M ]]что позволяет добавить что-то еще что вы могли бы сделать с
[[ ]]кроме арифметики питания.
этот код также может сравнивать поплавки. Он использует 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= op= num2= 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
Я решил это с помощью небольшой функции для преобразования строк версии в простые целочисленные значения, которые можно сравнить:
function versionToInt() { local IFS=. parts=() let val=1000000*parts[0]+1000*parts[1]+parts[2] echo $val }это делает два важных допущения:
- вход-это "нормальный SemVer строку"
- каждая часть находится между 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
Если у вас есть поплавки, вы можете написать функцию, а затем использовать ее, например
#!/bin/bash function float_gt() { perl -e "{if(>){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
Comments