BashScripts.org
http://bashscripts.org/forum/

Need help- Comparing version numbers
http://bashscripts.org/forum/viewtopic.php?f=16&t=1248
Page 1 of 1

Author:  kirann_hegde [ Thu Nov 18, 2010 9:14 am ]
Post subject:  Need help- Comparing version numbers

Hello,

I am a complete newbie to shell scripting. All my exposure has been to the windows platforms all these years.
I have just started working on shell scripts.

I have a problem wherein i need to compare two version numbers.
The version numbers have the format: <major>.<minor>.<build>.<revision>.
So essentially what this means is that: 1.01.02.03 is the same as 1.1.2.3.

I do not see a direct way to compare version numbers in shell scripting. All of the functions provided such as expr, bc etc do not handle cases which involves comparing version numbers such as 1.01.02.03 & 1.1.2.3.

Could anyone please guide me as to how i could achieve fool proof version number comparison in shell scripting?
If anyone could provide me with the piece of script, it would be great.


Second question:
How do i convert strings to numbers in shell scripting?

I am running short of time. Any help would be very much appreciated.

Regards,
Kiran Hegde

Author:  Patsie [ Thu Nov 18, 2010 2:41 pm ]
Post subject:  Re: Need help- Comparing version numbers

As long as all your versions contain exactly four numbers, this should work.
Code:
#!/bin/bash

function version { echo "[email protected]" | awk -F. '{ printf("%d.%d.%d.%d\n", $1,$2,$3,$4); }'; }

if [ $(version 1.1.2.3) = $(version 1.01.02.00003) ]; then
  echo "equal"
else
  echo "not equal"
fi

Author:  kirann_hegde [ Thu Nov 18, 2010 10:38 pm ]
Post subject:  Re: Need help- Comparing version numbers

Hello,

Thanks for the quick response. My versions are not always intended to contain 4 numbers. I would have to zero pad them.
Let me try this and let you know if it meets my expectations.

Thanks again
Kiran Hegde

Author:  kirann_hegde [ Fri Nov 19, 2010 5:19 am ]
Post subject:  Re: Need help- Comparing version numbers

Hello,

I tried the following and it did **not** work


#!/bin/sh
function version { echo "[email protected]" | awk -F. '{ printf("%d.%d.%d.%d\n", $1,$2,$3,$4);
}'; }

if [ $(version 1.11.2.301) < $(version 1.011.02.000030) ]; then
echo "equal"
else
echo "not equal"
fi

Any ideas why?

Regards,
Kiran Hegde

Author:  Patsie [ Fri Nov 19, 2010 2:05 pm ]
Post subject:  Re: Need help- Comparing version numbers

What you're doing there is wrong in a number of ways.
First: You're using a '<' which in shell script means: input redirection. If you want to use 'less than' in a test statement, use '-lt'
b) You're comparing 2 strings as though they were numbers
#3. In your OP you did not specify in what way you wanted to compare the version numbers. So I took the easy way and wrote a (not)equals comparison. If you want a 'less than'/'greater than' comparison you should have specified...

Author:  kirann_hegde [ Sun Nov 21, 2010 1:24 am ]
Post subject:  Re: Need help- Comparing version numbers

One question though: Why was = used instead of lt in your first response?
And also, isnt it the case that strings which contain numbers are treated as numbers in bash?

I am a complete newbie . So please excuse my ignorance

Do you know of any good links to get started with shell scripting

Author:  Patsie [ Sun Nov 21, 2010 2:58 am ]
Post subject:  Re: Need help- Comparing version numbers

The '=' was used to compare if the 2 version strings were equal. I didn't use '-lt' because that's an operator for numbers only and means 'less than'.
Variables containing only numbers can be treated as numbers in tests. The versions strings here do not only contain numbers, but also periods. Therefor they are strings.
The best way to start learning shell script, is to actually do shell script. Solve a problem in your head or on paper and try to implement it in code. If you get stuck forums like these are a good playground to see if somebody has a solution for your impediment. Most programming forums are not there to solve the problem itself, only to solve programming issues.

Author:  choroba [ Mon Nov 22, 2010 8:13 am ]
Post subject:  Re: Need help- Comparing version numbers

You can split your version strings into components and compare those. Something like this:
Code:
eval major=${version/./ minor=}
eval minor=${minor/./ build=}
eval build=${build/./ revision=}
if (( major < major2 )) ; then
...
fi

But be careful with leading zeros:
Code:
((012 < 11 )) && echo less

returns "less", because 012 is treated as octal, i.e. 10 in decimal!

Author:  Patsie [ Mon Nov 22, 2010 1:52 pm ]
Post subject:  Re: Need help- Comparing version numbers

I'd rather go for something like this:
Code:
#!/bin/sh

function version { echo "[email protected]" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }

if [ $(version 10.1.2.4) -gt $(version 10.01.02.003) ]; then
  echo "$ver1 is newer $ver2"
else
  echo "$ver1 is NOT newer $ver2"
fi

It's not perfect either, don't get me wrong :)

Author:  choroba [ Mon Nov 22, 2010 6:37 pm ]
Post subject:  Re: Need help- Comparing version numbers

Patsie wrote:
It's not perfect either, don't get me wrong :)

Yes, it still takes 012 to be octal 10.

Author:  Patsie [ Mon Nov 22, 2010 11:30 pm ]
Post subject:  Re: Need help- Comparing version numbers

Ehm, no. That one is fixed by the awk. The first number is printed as %d which strips leading zeros.

Author:  kirann_hegde [ Thu Nov 25, 2010 8:10 am ]
Post subject:  Re: Need help- Comparing version numbers

I finally wrote a script to compare version numbers. Irrespective of how many significant digits are present in the version numbers, this works pretty well.
I used /bin/sh which defaults to Bourne shell and on some systems to bash.
Hence i could not use arrays.
Here is the code for the same:
#returns 0 for greater than
#returns 1 for less than
#returns 2 for equals
compare_ver_numbers()
{
#read the input parameters to the function
version1=$1
version2=$2
i=1


#zero pad the version strings
version1=`echo $version1 | awk -F"." '{printf("%d.%d.%d.%d",$1,$2,$3,$4); }'`
version2=`echo $version2 | awk -F"." '{printf("%d.%d.%d.%d",$1,$2,$3,$4); }'`

#Use a while loop to compare the individual elements of the array
#We are using bourne shell for compatibility across all flavours of unix.As a result of this, arrays are not supported in Bourne shell.
#Hence we have to resort to the method which has been used.


while [ $i -le 4 ]

do
if [ $i -eq 1 ]
then
val1=`echo $version1 | awk -F"." '{print $1}'`
val2=`echo $version2 | awk -F"." '{print $1}'`
fi

if [ $i -eq 2 ]
then
val1=`echo $version1 | awk -F"." '{print $2}'`
val2=`echo $version2 | awk -F"." '{print $2}'`
fi

if [ $i -eq 3 ]
then
val1=`echo $version1 | awk -F"." '{print $3}'`
val2=`echo $version2 | awk -F"." '{print $3}'`
fi

if [ $i -eq 4 ]
then
val1=`echo $version1 | awk -F"." '{print $4}'`
val2=`echo $version2 | awk -F"." '{print $4}'`
fi

if [ $val1 -gt $val2 ]
then
return 0
fi

if [ $val1 -lt $val2 ] ; then
return 1
fi
i=`expr $i + 1`


done

#If the control reaches here, it means both of the versions are equal
return 2


}

Is there a better way to do this? I had earlier used arrays. However arrays are not supported by Bourne shell. Hence i had to resort to the above method.Please let me know.

Regards,
Kiran Hegde

Author:  choroba [ Fri Nov 26, 2010 3:42 pm ]
Post subject:  Re: Need help- Comparing version numbers

Patsie wrote:
Ehm, no. That one is fixed by the awk. The first number is printed as %d which strips leading zeros.

I stand corrected. But it says
Code:
10.1.2.9 is NOT newer 10.01.02.008

Is it correct?

Author:  DarthWavy [ Fri Nov 26, 2010 4:35 pm ]
Post subject:  Re: Need help- Comparing version numbers

Code:
[[email protected] ~]# function version { echo "[email protected]" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
[[email protected] ~]# ver1=10.1.2.9
[[email protected] ~]# ver2=10.01.02.008
[[email protected] ~]# if [ $(version $ver1) -gt $(version $ver2) ]; then   echo "$ver1 is newer $ver2"; else   echo "$ver1 is NOT newer $ver2"; fi
10.1.2.9 is newer 10.01.02.008

^^ looks good to me

Author:  Patsie [ Sat Nov 27, 2010 2:02 am ]
Post subject:  Re: Need help- Comparing version numbers

Code:
$>cat ./test.sh
#!/bin/bash

ver1="10.1.2.9"
ver2="10.01.02.008"

function version { echo "[email protected]" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }

if [ $(version $ver1) -gt $(version $ver2) ]; then
  echo "$ver1 is newer than $ver2"
else
  echo "$ver1 is NOT newer than $ver2"
fi

$>./test.sh
10.1.2.9 is newer than 10.01.02.008



Yeah, it looks fine here too...

Author:  choroba [ Sat Nov 27, 2010 2:55 pm ]
Post subject:  Re: Need help- Comparing version numbers

Stupid mistake on my side, I apologize.

Author:  sgreenman [ Thu Feb 17, 2011 11:52 am ]
Post subject:  Re: Need help- Comparing version numbers

I had the need to compare version numbers in a bash script, but wasn't satisfied with the existing answers, so poked around a bit. I found that the sort command has a --version-sort option that seems relatively smart about this, so I used it.


!/bin/bash

function vercomp {
[ ! $(echo -e "$1\n$2" | sort --version-sort | head -1) = "$2" ]
}

function test {
echo Testing that $1 \< $2
vercomp $1 $2 || echo "FAIL"
vercomp $2 $1 && echo "FAIL reversed"
vercomp $1 $1 && echo "FAIL $1 < $1"
vercomp $2 $2 && echo "FAIL $2 < $2"
}

test 1.0 1.1
test 1 1.000000001
test 1 2
test 1.1.1.1.1.2 1.1.1.1.1.3
test 1.1.1.1 1.01.001.0001.00001
test 10.01.02.008 10.1.2.9
test 1.0 1.0a
test 1.0 1.0.a

Author:  Patsie [ Thu Feb 17, 2011 2:00 pm ]
Post subject:  Re: Need help- Comparing version numbers

ohw, that's a very nice feature indeed. I was not aware of it yet.
You live and learn :)

Page 1 of 1 All times are UTC - 6 hours
© 2000, 2002, 2005, 2007 phpBB Group • http://www.phpbb.com