Recently I needed a simple way to compare semver strings in a BASH script and was unable to find a solution that I liked so I wrote one. Why almost-native BASH? Leveraging the common available sort
utility avoids re-implementing the version sort logic, reduces potential bugs and size of the function to a simple 3 lines vs 30+ lines for most BASH-native solutions.
This is working well in environments I manage. If you notice any bugs or issues please comment.
Function returns a standard -1, 0, 1 response. Basic unit tests included to validate functionality and provide example usage.
Enjoy!
#!/usr/bin/env bash
function semver_check {
# sort low->high then pick the last one (highest)
local HV; HV=$(echo -e "$1\n$2" |sort -V |tail -1)
# They're not the same and $1 is not the high version = -1
[[ "$1" != "$2" && "$1" != "$HV" ]] && echo -1 && return
# 0 = they're the same; 1 = not the same
[[ "$1" == "$2" ]]; echo $?
}
#
# TESTS
#
LV="1.2.3"
HV="2.3.4"
ARGS=("Test A: Ver1 == Ver2" "$LV" "$LV")
echo -n "${ARGS[*]} "
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -eq 0 ]] && echo "PASS" || echo "FAIL"
ARGS=("Test B: Ver1 < Ver2" "$LV" "$HV")
echo -n "${ARGS[*]} "
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -lt 0 ]] && echo "PASS" || echo "FAIL"
ARGS=("Test C: Ver1 > Ver2" "$HV" "$LV")
echo -n "${ARGS[*]} "
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -gt 0 ]] && echo "PASS" || echo "FAIL"
ARGS=("Test D: Ver1 >= Ver2" "$HV" "$LV")
echo -n "${ARGS[*]} "
RESULT="PASS"
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -ge 0 ]] || RESULT="FAIL"
[[ $(semver_check "${ARGS[1]}" "${ARGS[1]}") -ge 0 ]] || RESULT="FAIL"
echo ${RESULT}
ARGS=("Test E: Ver1 <= Ver2" "$LV" "$HV")
echo -n "${ARGS[*]} "
RESULT="PASS"
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -le 0 ]] || RESULT="FAIL"
[[ $(semver_check "${ARGS[1]}" "${ARGS[1]}") -le 0 ]] || RESULT="FAIL"
echo ${RESULT}
Addendum: The sort
binary dependency must support natural version sort option (-V, --version-sort
) This option is available on GNU coreutils 7+ and is also available on Mac OS 10.14+