Skip to content

Instantly share code, notes, and snippets.

@hrvoj3e
Forked from Ariel-Rodriguez/semver.sh
Created October 10, 2019 19:13
Show Gist options
  • Save hrvoj3e/03d9a184aeb9c08ef5e44924185b87a4 to your computer and use it in GitHub Desktop.
Save hrvoj3e/03d9a184aeb9c08ef5e44924185b87a4 to your computer and use it in GitHub Desktop.
semver compare tool in bash
#!/bin/bash
###
# semantic version comparition using semver specification http://semver.org/
# This bash script compares pre-releases alphabetically as well
#
# returns 1 when A greater than B
# returns 0 when A equals B
# returns -1 when A lower than B
#
# Usage
# chmod +x semver.sh
# ./semver.sh 1.0.0 v1.0.0-rc.0
# --> 1
#
# Author Ariel Rodriguez
# License MIT
###
semver_compare() {
local version_a version_b pr_a pr_b
# strip word "v" and extract first subset version (x.y.z from x.y.z-foo.n)
version_a=$(echo "${1//v/}" | awk -F'-' '{print $1}')
version_b=$(echo "${2//v/}" | awk -F'-' '{print $1}')
if [ "$version_a" \= "$version_b" ]
then
# check for pre-release
# extract pre-release (-foo.n from x.y.z-foo.n)
pr_a=$(echo "$1" | awk -F'-' '{print $2}')
pr_b=$(echo "$2" | awk -F'-' '{print $2}')
####
# Return 0 when A is equal to B
[ "$pr_a" \= "$pr_b" ] && echo 0 && return 0
####
# Return 1
# Case when A is not pre-release
if [ -z "$pr_a" ]
then
echo 1 && return 0
fi
####
# Case when pre-release A exists and is greater than B's pre-release
# extract numbers -rc.x --> x
number_a=$(echo ${pr_a//[!0-9]/})
number_b=$(echo ${pr_b//[!0-9]/})
[ -z "${number_a}" ] && number_a=0
[ -z "${number_b}" ] && number_b=0
[ "$pr_a" \> "$pr_b" ] && [ -n "$pr_b" ] && [ "$number_a" -gt "$number_b" ] && echo 1 && return 0
####
# Retrun -1 when A is lower than B
echo -1 && return 0
fi
arr_version_a=(${version_a//./ })
arr_version_b=(${version_b//./ })
cursor=0
# Iterate arrays from left to right and find the first difference
while [ "$([ "${arr_version_a[$cursor]}" -eq "${arr_version_b[$cursor]}" ] && [ $cursor -lt ${#arr_version_a[@]} ] && echo true)" == true ]
do
cursor=$((cursor+1))
done
[ "${arr_version_a[$cursor]}" -gt "${arr_version_b[$cursor]}" ] && echo 1 || echo -1
}
[ -n "$1" ] && echo $(semver_compare $1 $2)
#!/bin/bash
# Include semver_compare tool
source ./semver.sh
versions=(
0.0.0 0.0.0 0
0.0.1 0.0.0 1
0.0.0 0.0.1 -1
0.0.1-rc v0.0.1-rc 0
0.0.1-rc.1 v0.0.1-rc 1
0.0.1-rc.0 v0.0.1-rc.2 -1
v0.0.1-rc.0 0.0.1-rc.0 0
v0.0.1 v0.0.1-rc.2 1
v0.0.1 v0.0.1 0
v0.1.0-rc.0 0.1.0-rc.1 -1
0.1.0-rc.1 v0.1.0-rc.1 0
v0.1.0 v0.1.0-rc.1 1
v0.1.0-rc.1 v0.1.0 -1
v0.1.0-rc.9 v0.1.0-rc.10 -1
v0.1.0-alpha v0.1.0-beta -1
v0.1.0-alpha.1 v0.1.0-beta.0 -1
)
_assert_is() {
echo $1 $2 is expected to be $4 $(if [ $3 == $4 ]; then echo "OK"; else echo FAIL got $3; fi)
}
for (( i=0; i<=$(( ${#versions[@]} -3 )); i+=3 ))
do
echo compare $(_assert_is ${versions[i]} ${versions[ i + 1]} $(semver_compare ${versions[i]} ${versions[ i + 1]}) ${versions[i+2]})
done
# compare 0.0.1-rc.0 v0.0.1-rc.2 is expected to be -1 OK
# compare v0.0.1-rc.0 0.0.1-rc.0 is expected to be 0 OK
# compare v0.0.1 v0.0.1-rc.2 is expected to be 1 OK
# compare v0.0.1 v0.0.1 is expected to be 0 OK
# compare v0.1.0-rc.0 0.1.0-rc.1 is expected to be -1 OK
# compare 0.1.0-rc.1 v0.1.0-rc.1 is expected to be 0 OK
# compare v0.1.0 v0.1.0-rc.1 is expected to be 1 OK
# compare v0.1.0-rc.1 v0.1.0 is expected to be -1 OK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment