Page MenuHome GnuPG

cmp_version_in_the_rpm_way.sh

Authored By
gniibe
Aug 31 2018, 6:49 AM
Size
3 KB
Subscribers
None

cmp_version_in_the_rpm_way.sh

# I read this blog entry:
# https://blog.jasonantman.com/2014/07/how-yum-and-rpm-compare-versions/
#
# And.. write this one
# This is more correct than the description above
#
arg1_is_same () {
[ "$1" = "==" -o "$1" = ">=" -o "$1" = "<=" ]
}
arg1_is_less () {
[ "$1" = "!=" -o "$1" = "<" -o "$1" = "<=" ]
}
arg1_is_great () {
[ "$1" = "!=" -o "$1" = ">" -o "$1" = ">=" ]
}
eval_compare_version () {
local str1="$1"
local cmp="$2"
local str2="$3"
local char1 char2
local chunk1 chunk2
while [ -n "$str1" -a -n "$str2" ]; do
# 1. Trim anything that's not alnum or tilde from the front
str1="$(expr "$str1" : '[^0-9A-Za-z~]*\(.*\)')"
str2="$(expr "$str2" : '[^0-9A-Za-z~]*\(.*\)')"
# Get the first character
char1=${str1%${str1#?}}
char2=${str2%${str2#?}}
if [ "$char1" = ~ -o "$char2" = ~ ]; then
# 3.B If STR2 starts with a tilde and STR1 does not, STR2
# is older.
if [ "$char1" != ~ ]; then
arg1_is_great $cmp
return
fi
# 3.A If STR1 starts with a tilde and STR2 does not, STR1
# is older.
if [ "$char2" != ~ ]; then
arg1_is_less $cmp
return
fi
# 2. If both start with a tilde, discard it and move on to
# the next character.
str1=${str1#~}
str2=${str2#~}
continue
fi
# 4. End the loop if either string has reached zero length.
if [ -z "$char1" -o -z "$char2" ]; then
break
fi
# 5. If the first character of STR1 is a digit, pop the leading
# chunk of continuous digits from each string. If STR1 begins
# with a letter, do the same for leading letters.
# 6. If the chunk from STR2 had 0 length, STR1 is newer if
# chunk from STR1 was numeric, or older if it was
# alphabetic.
case "$char1$char2" in
[0-9][A-Za-z])
arg1_is_great $cmp
return
;;
[A-Za-z][0-9])
arg1_is_less $cmp
return
;;
[0-9][0-9])
chunk1="$(expr "$str1" : '\([0-9]*\)')"
chunk2="$(expr "$str2" : '\([0-9]*\)')"
;;
[A-Za-z][A-Za-z])
chunk1="$(expr "$str1" : '\([A-Za-z]*\)')"
chunk2="$(expr "$str2" : '\([A-Za-z]*\)')"
;;
esac
# 7. Compare chunks numerically if digits, or lexicographically
# (Luckyly, expr just can do that)
if expr "$chunk1" "!=" "$chunk2" >/dev/null; then
if expr "$chunk1" ">" "$chunk2" >/dev/null; then
arg1_is_great $cmp
return
else
arg1_is_less $cmp
return
fi
fi
# Remove the chunk
str1="${str1#$chunk1}"
str2="${str2#$chunk2}"
done
# Either STR1, STR2 or both is empty here
# !!! Watch out tilda here, too !!!
if [ -n "$str1" ]; then
case "$str1" in
~*) arg1_is_less $cmp ;;
*) arg1_is_great $cmp ;;
esac
elif [ -n "$str2" ]; then
case "$str2" in
~*) arg1_is_great $cmp ;;
*) arg1_is_less $cmp ;;
esac
else
arg1_is_same $cmp
fi
}
eval_compare_version $*
# Run by dash or bash
# dash cmp_version_in_the_rpm_way.sh 2.0.99 '>=' 2.1 || echo 2.0.99 is older
# dash cmp_version_in_the_rpm_way.sh 1.9~rc1 '<' 1.9 && echo 1.9~rc1 is older
# dash cmp_version_in_the_rpm_way.sh 3.1b '<=' 3.1 || echo 3.1b is newer

File Metadata

Mime Type
text/plain
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
260018

Event Timeline