Skip to content

Instantly share code, notes, and snippets.

@karlkfi
Created May 16, 2017 21:33
Show Gist options
  • Save karlkfi/892322c27d4f72fb8dff170beab2549b to your computer and use it in GitHub Desktop.
Save karlkfi/892322c27d4f72fb8dff170beab2549b to your computer and use it in GitHub Desktop.
Compare two semantic versions in bash
# return 0 if version A >= version B using semanatic versioning
function semver_gte() {
VERISON_A="${1}"
VERISON_B="${2}"
SEMVER_PATTERN="[^0-9]*\([0-9][0-9]*\)[.]\([0-9][0-9]*\)[.]\([0-9][0-9]*\).*"
SEG1_A="$(echo "${VERISON_A}" | sed -e "s#${SEMVER_PATTERN}#\1#")"
SEG1_B="$(echo "${VERISON_B}" | sed -e "s#${SEMVER_PATTERN}#\1#")"
[[ ${SEG1_A} < ${SEG1_B} ]] && return 1
[[ ${SEG1_A} > ${SEG1_B} ]] && return 0
SEG2_A="$(echo "${VERISON_A}" | sed -e "s#${SEMVER_PATTERN}#\2#")"
SEG2_B="$(echo "${VERISON_B}" | sed -e "s#${SEMVER_PATTERN}#\2#")"
[[ ${SEG2_A} < ${SEG2_B} ]] && return 1
[[ ${SEG2_A} > ${SEG2_B} ]] && return 0
SEG3_A="$(echo "${VERISON_A}" | sed -e "s#${SEMVER_PATTERN}#\3#")"
SEG3_B="$(echo "${VERISON_B}" | sed -e "s#${SEMVER_PATTERN}#\3#")"
[[ ${SEG3_A} < ${SEG3_B} ]] && return 1
return 0
}
if semver_gte "${VERSION}" "0.5.0"; then
echo "${VERSION} >= 0.5.0"
else
echo "${VERSION} < 0.5.0"
fi
@analogue
Copy link

This has a bug since integer comparisons using < and > require double parentheses. Failing test case: semver_gte "5.10.0" "5.8.0"

Fixed version

#!/bin/bash
semver_gte() {
  local VERISON_A="${1}"
  local VERISON_B="${2}"
  local SEMVER_PATTERN="[^0-9]*\([0-9][0-9]*\)[.]\([0-9][0-9]*\)[.]\([0-9][0-9]*\).*"
  local SEG1_A="$(echo "${VERISON_A}" | sed -e "s#${SEMVER_PATTERN}#\1#")"
  local SEG1_B="$(echo "${VERISON_B}" | sed -e "s#${SEMVER_PATTERN}#\1#")"
  (( ${SEG1_A} < ${SEG1_B} )) && return 1
  (( ${SEG1_A} > ${SEG1_B} )) && return 0
  local SEG2_A="$(echo "${VERISON_A}" | sed -e "s#${SEMVER_PATTERN}#\2#")"
  local SEG2_B="$(echo "${VERISON_B}" | sed -e "s#${SEMVER_PATTERN}#\2#")"
  (( ${SEG2_A} < ${SEG2_B} )) && return 1
  (( ${SEG2_A} > ${SEG2_B} )) && return 0
  local SEG3_A="$(echo "${VERISON_A}" | sed -e "s#${SEMVER_PATTERN}#\3#")"
  local SEG3_B="$(echo "${VERISON_B}" | sed -e "s#${SEMVER_PATTERN}#\3#")"
  (( ${SEG3_A} < ${SEG3_B} )) && return 1
  return 0
}


compare() {
    local V1="${1}"
    local V2="${2}"
    if semver_gte $V1 $V2; then
      echo "${V1} >= ${V2}"
    else
      echo "${V1} < ${V2}"
    fi
}

compare "5.8.0" "5.10.0"
compare "5.10.0" "5.8.0"
compare "5.8.0" "5.8.0"
compare "1.1.1" "1.1.20"
compare "1.1.20" "1.1.1"
compare "1.2.3" "4.5.6"
compare "4.5.6" "1.2.3"

Output

5.8.0 < 5.10.0
5.10.0 >= 5.8.0
5.8.0 >= 5.8.0
1.1.1 < 1.1.20
1.1.20 >= 1.1.1
1.2.3 < 4.5.6
4.5.6 >= 1.2.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment