Skip to content

Instantly share code, notes, and snippets.

@ObserverOfTime
Forked from Ariel-Rodriguez/semver.sh
Last active June 10, 2019 17:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ObserverOfTime/761d89b39d77b5d3fce2da9564a78b45 to your computer and use it in GitHub Desktop.
Save ObserverOfTime/761d89b39d77b5d3fce2da9564a78b45 to your computer and use it in GitHub Desktop.
you might wanna use https://github.com/bb010g/Semver.sh instead
#!/bin/bash -e
###
# Semantic version comparison 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: ObserverOfTime
# License: MIT
# Based on: https://git.io/fSGBC by Ariel Rodriguez
###
semver_compare() {
local version_a version_b
version_a="$(grep -Eo '^[0-9\.]*' <<< "${1#v}")"
version_b="$(grep -Eo '^[0-9\.]*' <<< "${2#v}")"
if [[ "$version_a" == "$version_b" ]]; then
local spec_a spec_b spec_ch_a spec_ch_b spec_num_a spec_num_b
spec_a="$(sed -e "s/^${version_a}[-\\.\\+~]*//" <<< "${1#v}")"
spec_b="$(sed -e "s/^${version_b}[-\\.\\+~]*//" <<< "${2#v}")"
[[ "$spec_a" == "$spec_b" ]] && echo 0 && return 0
[ -z "${spec_a}" ] && echo 1 && return 0
[ -z "${spec_b}" ] && echo -1 && return 0
spec_ch_a="$(grep -Eo '^[A-Za-z]*' <<< "$spec_a")"
spec_ch_b="$(grep -Eo '^[A-Za-z]*' <<< "$spec_b")"
[[ "$spec_ch_a" > "$spec_ch_b" ]] && echo 1 && return 0
[[ "$spec_ch_a" < "$spec_ch_b" ]] && echo -1 && return 0
spec_num_a="$(sed -e "s/^${spec_ch_a}[\\.-]*//" <<< "$spec_a")"
spec_num_b="$(sed -e "s/^${spec_ch_b}[\\.-]*//" <<< "$spec_b")"
semver_compare "$spec_num_a" "$spec_num_b" && return 0
fi
local arr_version_a arr_version_b index
IFS=. read -ra arr_version_a <<< "$version_a"
IFS=. read -ra arr_version_b <<< "$version_b"
index=0
while [ $index -lt ${#arr_version_a[@]} ] && \
[ "${arr_version_a[$index]}" -eq "${arr_version_b[$index]}" ]; do
[ $((++index)) -eq ${#arr_version_a[@]} ] && echo 0 && return 0
done
[ "${arr_version_a[$index]}" -gt "${arr_version_b[$index]}" ] \
&& echo 1 || echo -1
return 0
}
[ -n "$1" ] && semver_compare "$1" "$2"
#!/bin/bash
source ./semver.sh
versions=(
'0.0.1 0.0.0 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'
'0.1.0-alpha1.0 0.1.0-beta0.1 -1'
'2.4.0-1 2.4.0-2 -1'
'1.3.0-beta 1.3.0beta 0'
'v0.2.0-rc.1.0 v0.2.0-rc0.1 1'
'v1.2.0+git.ab27ce9 v1.2.0-alpha 1'
'v1.2.0~20180304 v1.2.0~20180302 1'
'v1.2.0-alpha v1.2.0~20180201 1'
)
_assert() {
local actual
actual="$(semver_compare "$1" "$2")"
printf 'semver_compare %s %s is expected to be %d:' "$1" "$2" "$3"
printf ' %s\n' "$([ "$3" == "$actual" ] && \
echo 'OK' || echo "FAIL, got $actual")"
}
for ((i=0; i<${#versions[@]}; ++i )); do
version_a="$(awk '{print $1}' <<< "${versions[i]}")"
version_b="$(awk '{print $2}' <<< "${versions[i]}")"
_expected="$(awk '{print $3}' <<< "${versions[i]}")"
_assert "$version_a" "$version_b" "$_expected"
done
unset versions version_a version_b _expected
unset -f _assert
# semver_compare 0.0.1 0.0.0 is expected to be 1: OK
# semver_compare 0.0.1-rc.0 v0.0.1-rc.2 is expected to be -1: OK
# semver_compare v0.0.1-rc.0 0.0.1-rc.0 is expected to be 0: OK
# semver_compare v0.0.1 v0.0.1-rc.2 is expected to be 1: OK
# semver_compare v0.0.1 v0.0.1 is expected to be 0: OK
# semver_compare v0.1.0-rc.0 0.1.0-rc.1 is expected to be -1: OK
# semver_compare 0.1.0-rc.1 v0.1.0-rc.1 is expected to be 0: OK
# semver_compare v0.1.0 v0.1.0-rc.1 is expected to be 1: OK
# semver_compare v0.1.0-rc.1 v0.1.0 is expected to be -1: OK
# semver_compare 0.1.0-alpha1.0 0.1.0-beta0.1 is expected to be -1: OK
# semver_compare 2.4.0-1 2.4.0-2 is expected to be -1: OK
# semver_compare 1.3.0-beta 1.3.0beta is expected to be 0: OK
# semver_compare v0.2.0-rc.1.0 v0.2.0-rc0.1 is expected to be 1: OK
# semver_compare v1.2.0+git.ab27ce9 v1.2.0-alpha is expected to be 1: OK
# semver_compare v1.2.0~20180304 v1.2.0~20180302 is expected to be 1: OK
# semver_compare v1.2.0-alpha v1.2.0~20180201 is expected to be 1: OK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment