Skip to content

Instantly share code, notes, and snippets.

@andkirby
Last active January 12, 2024 15:28
Show Gist options
  • Save andkirby/54204328823febad9d34422427b1937b to your computer and use it in GitHub Desktop.
Save andkirby/54204328823febad9d34422427b1937b to your computer and use it in GitHub Desktop.
Semantic versions sorting in bash.
#!/usr/bin/env bash
# Download this gist
# curl -Ls https://gist.github.com/andkirby/54204328823febad9d34422427b1937b/raw/semversort.sh | bash
# And run:
# $ semversort 1.0 1.0-rc 1.0-patch 1.0-alpha
# or in GIT
# $ semversort $(git tag)
# Using pipeline:
# $ echo 1.0 1.0-rc 1.0-patch 1.0-alpha | semversort
#
# 2016-11-03
# Released.
# 2020-03-10
# Changed regular part from "[A-z]" to "[A-Za-z]"
set -o errexit
set -o pipefail
set -o nounset
#set -o xtrace
# Script running with pipeline
if [ -z "${BASH_SOURCE[0]:-}" ]; then
__dir=/usr/local/bin
if [ ! -d ${__dir} ]; then
__dir=/usr/bin
fi
__file=${__dir}/semversort
curl -Ls https://gist.github.com/andkirby/54204328823febad9d34422427b1937b/raw/semversort.sh -o ${__file} && \
chmod u+x ${__file} && \
echo 'Semantic version sort: '${__file} && \
exit 0
exit 1
fi
if [ -t 0 ]; then
versions_list=$@
else
# catch pipeline output
versions_list=$(cat)
fi
version_weight () {
echo -e "$1" | tr ' ' "\n" | sed -e 's:\+.*$::' | sed -e 's:^v::' | \
sed -re 's:^[0-9]+(\.[0-9]+)+$:&-stable:' | \
sed -re 's:([^A-Za-z])dev\.?([^A-Za-z]|$):\1.10.\2:g' | \
sed -re 's:([^A-Za-z])(alpha|a)\.?([^A-Za-z]|$):\1.20.\3:g' | \
sed -re 's:([^A-Za-z])(beta|b)\.?([^A-Za-z]|$):\1.30.\3:g' | \
sed -re 's:([^A-Za-z])(rc|RC)\.?([^A-Za-z]|$)?:\1.40.\3:g' | \
sed -re 's:([^A-Za-z])stable\.?([^A-Za-z]|$):\1.50.\2:g' | \
sed -re 's:([^A-Za-z])pl\.?([^A-Za-z]|$):\1.60.\2:g' | \
sed -re 's:([^A-Za-z])(patch|p)\.?([^A-Za-z]|$):\1.70.\3:g' | \
sed -r 's:\.{2,}:.:' | \
sed -r 's:\.$::' | \
sed -r 's:-\.:.:'
}
tags_orig=(${versions_list})
tags_weight=( $(version_weight "${tags_orig[*]}") )
keys=$(for ix in ${!tags_weight[*]}; do
printf "%s+%s\n" "${tags_weight[${ix}]}" ${ix}
done | sort -V | cut -d+ -f2)
for ix in ${keys}; do
printf "%s\n" ${tags_orig[${ix}]}
done
@andkirby
Copy link
Author

andkirby commented Mar 4, 2019

@leifhetle thanks for this note.
@Wolvverine, yeah, it doesn't work. But it works with this one:
https://gist.github.com/andkirby/0046df5cad44f86b670a102b7c8b7ba7/raw/version_sort_install.sh
Yeah, that's PHP function. Seems it's not what you are looking for.

Just tested sed original script on Ubuntu - it does work

# sed --version
sed (GNU sed) 4.4

@waja
Copy link

waja commented Apr 1, 2023

How about just sort -V? :)

       -V, --version-sort
              natural sort of (version) numbers within text

@andkirby
Copy link
Author

andkirby commented Apr 2, 2023

@waja here is Stack Overflow thread:
It might help you find a proper solution which might work for you.

But in a nutshell, no, "sort -V" does not work (as initially I was needed to use -patch suffixes), you may see it in this answer.

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