How to compare two strings in dot separated version format in Bash? How to compare two strings in dot separated version format in Bash? linux linux

How to compare two strings in dot separated version format in Bash?


Here is a pure Bash version that doesn't require any external utilities:

#!/bin/bashvercomp () {    if [[ $1 == $2 ]]    then        return 0    fi    local IFS=.    local i ver1=($1) ver2=($2)    # fill empty fields in ver1 with zeros    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))    do        ver1[i]=0    done    for ((i=0; i<${#ver1[@]}; i++))    do        if [[ -z ${ver2[i]} ]]        then            # fill empty fields in ver2 with zeros            ver2[i]=0        fi        if ((10#${ver1[i]} > 10#${ver2[i]}))        then            return 1        fi        if ((10#${ver1[i]} < 10#${ver2[i]}))        then            return 2        fi    done    return 0}testvercomp () {    vercomp $1 $2    case $? in        0) op='=';;        1) op='>';;        2) op='<';;    esac    if [[ $op != $3 ]]    then        echo "FAIL: Expected '$3', Actual '$op', Arg1 '$1', Arg2 '$2'"    else        echo "Pass: '$1 $op $2'"    fi}# Run tests# argument table format:# testarg1   testarg2     expected_relationshipecho "The following tests should pass"while read -r testdo    testvercomp $testdone << EOF1            1            =2.1          2.2          <3.0.4.10     3.0.4.2      >4.08         4.08.01      <3.2.1.9.8144 3.2          >3.2          3.2.1.9.8144 <1.2          2.1          <2.1          1.2          >5.6.7        5.6.7        =1.01.1       1.1.1        =1.1.1        1.01.1       =1            1.0          =1.0          1            =1.0.2.0      1.0.2        =1..0         1.0          =1.0          1..0         =EOFecho "The following test should fail (test the tester)"testvercomp 1 1 '>'

Run the tests:

$ . ./vercompThe following tests should passPass: '1 = 1'Pass: '2.1 < 2.2'Pass: '3.0.4.10 > 3.0.4.2'Pass: '4.08 < 4.08.01'Pass: '3.2.1.9.8144 > 3.2'Pass: '3.2 < 3.2.1.9.8144'Pass: '1.2 < 2.1'Pass: '2.1 > 1.2'Pass: '5.6.7 = 5.6.7'Pass: '1.01.1 = 1.1.1'Pass: '1.1.1 = 1.01.1'Pass: '1 = 1.0'Pass: '1.0 = 1'Pass: '1.0.2.0 = 1.0.2'Pass: '1..0 = 1.0'Pass: '1.0 = 1..0'The following test should fail (test the tester)FAIL: Expected '>', Actual '=', Arg1 '1', Arg2 '1'


If you have coreutils-7 (in Ubuntu Karmic but not Jaunty) then your sort command should have a -V option (version sort) which you could use to do the comparison:

verlte() {    [  "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ]}verlt() {    [ "$1" = "$2" ] && return 1 || verlte $1 $2}verlte 2.5.7 2.5.6 && echo "yes" || echo "no" # noverlt 2.4.10 2.4.9 && echo "yes" || echo "no" # noverlt 2.4.8 2.4.10 && echo "yes" || echo "no" # yesverlte 2.5.6 2.5.6 && echo "yes" || echo "no" # yesverlt 2.5.6 2.5.6 && echo "yes" || echo "no" # no


There probably is no universally correct way to achieve this. If you are trying to compare versions in the Debian package system try dpkg --compare-versions <first> <relation> <second>.