How to sort semantic versions in bash?
Solution 1
1. Custom script in bash
I implemented my own solution
The code a bit ugly, but it works.
Installation
$ curl -Ls https://gist.github.com/andkirby/0046df5cad44f86b670a102b7c8b7ba7/raw/version_sort_install.sh | bash
Semantic version sort: /usr/bin/semversort
$ semversort 1.0 1.0-rc 1.0-patch 1.0-alpha
1.0-alpha
1.0-rc
1.0
1.0-patch
2. Using semver in node
NOTE: All versions must follow the particular schema and it DOESN'T support "patch".
https://github.com/npm/node-semver/blob/master/README.md
$ npm install --global semver
C:\Users\u.user\.node\semver -> C:\Users\u.user\.node\node_modules\semver\bin\semver
[email protected] C:\Users\u.user\.node\node_modules\semver
$ ~/.node/semver 1.2.3 1.3.6-patch 1.3.6-beta 1.3.6 1.3.6-alpha 1.0.4
1.0.4
1.2.3
1.3.6-alpha
1.3.6-beta
1.3.6-patch
1.3.6
3. Using PHP and version_compare() in console
Also, the PHP native version_compare()
(with using PHP of course :)) here.
Solution 2
Well, we could trick sort -V
by adding a dummy character at the end of the string for lines that do not contain a hyphen:
$ echo "$versions" | sed '/-/!{s/$/_/}' | sort -V | sed 's/_$//'
v1.4.0-alpha
v1.4.0-alpha1
v1.4.0-patch
v1.4.0-patch2
v1.4.0-patch9
v1.4.0-patch10
v1.4.0
v1.5.0-alpha
v1.5.0-alpha1
v1.5.0-alpha2
v1.5.0-patch
v1.5.0-patch1
v1.5.0
Underscore lexically sorts after hyphen. That's the trick.
Solution 3
You can use Linux sort:
$ printf "1.0\n2.0\n2.12\n2.10\n1.2\n1.10" | sort -t "." -k1,1n -k2,2n -k3,3n
1.0
1.2
1.10
2.0
2.10
2.12
Source: https://gist.github.com/loisaidasam/b1e6879f3deb495c22cc#gistcomment-1613531
Solution 4
If you are using gplv2 (native osx) tooling, the answer by @Glenn Jack doesn't work unless using gsed.
This native awk command can substitute.
| awk '{ if ($1 ~ /-/) print; else print $0"_" ; }' |sort -rV | sed 's/_$//'
Solution 5
| sed -e 's/["\,\s]//g' \ # remove bad symbols: 1.2.3 1.2.3-123 1.2.3-patch
| sed '/-/! s/$/@999/' \ # replace releases: 1.2.3@999 1.2.3-123 1.2.3-patch
| sed 's/[\-\.]/@/g' \ # replaces separators: 1@2@3@999 1@2@3@123 1@2@3@patch
| sed 's/@patch/@9999@/' \ # replace patches: 1@2@3@999 1@2@3@123 1@2@3@9999
| sort -n -t @ -k1 -k2 -k3 -k4 \ # sort by numbers
| sed 's/@9999@/@patch/' \ # replace back 1@2@3@999 1@2@3@123 1@2@3@patch
| sed 's/@999//' \ # replace back 1@2@3 1@2@3@123 1@2@3@patch
| sed 's/@/./' \ # replace back 1.2@3 1.2@3@123 1.2@3@patch
| sed 's/@/./' \ # replace back 1.2.3 1.2.3@123 1.2.3@patch
| sed 's/@/-/' # replace back 1.2.3 1.2.3-123 1.2.3-patch
Related videos on Youtube
Kirby
Updated on September 15, 2022Comments
-
Kirby over 1 year
I would like to sort semantic versions (semver.org)
v1.4.0 v1.4.0-alpha v1.4.0-alpha1 v1.4.0-patch v1.4.0-patch9 v1.4.0-patch10 v1.4.0-patch2 v1.5.0 v1.5.0-alpha v1.5.0-alpha1 v1.5.0-alpha2 v1.5.0-patch v1.5.0-patch1
in proper way. For instance, as
version_compare()
does in PHP (it doesn't directly, but can be used for that).Of course,
sort -V|--version-sort
doesn't work here.$ echo 1.0 1.0-alpha | tr ' ' "\n" | sort --version-sort 1.0 1.0-alpha
Is there some exist approach?
P.S.
In common sense, it should follow this schema:
1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0 < 1.0.0-patch < 1.0.0-patch.1.
P.P.S.
Semver 2.0 doesn't support patches, but it's needed.
-
Bruno Laturner almost 6 yearsThe "-patch" requirement makes this incompatible with semver, so you should not call this semver. On the other hand, semver doesn't support third party patches, it's made only for official releases (in that case of a patch, the source developer should add 1 to the number in the PATCH section). If you're really pushing it, maybe it can be done with +metadata after the end of the version.
-
Kirby almost 6 yearsYeah, it's true. It doesn't support "patch" type versions. About meta data - package managers DO NOT consider meta data. They cutting it off. I'm talking about composer, exactly. So, there are might be issues.
-
Kirby almost 6 yearsit means, it will make unexpected result, you try to get 1.0.0 version there are two version, like: 1.0.0 and 1.0.0+super-patch.
-
-
Kirby over 7 yearsTrue. :) So, why you've added this? :)
-
glenn jackman over 7 yearsUm, because you didn't show us your expected output?
-
Kirby over 7 yearsSorry, if it's unclear. So, I've considered semver, it doesn't have patches... :( If you command will sort RC and beta, it can be an answer for question without patches.
-
shadowbq about 4 yearsThis can fail under macos, you should be using gsed
-
Potherca over 3 yearsThat doesn't work if there are release candidates, for instance 2.12-rc1 would be sorted after 2.12, when it should be before it.
-
Panoptik over 3 yearsVery thanks for such sort ability. It helps to sort proper semver versioning (while I not use suffixes e.g rc, alpha). My full command for fetching largest version from git looks next
git for-each-ref --sort=creatordate --format '%(refname)' refs/tags | grep -E "^refs/tags/${PREFIX_DASH}[0-9]+\.[0-9]+\.[0-9]+$" | grep -E "[0-9]+\.[0-9]+\.[0-9]+" -o | sort -t "." -k1,1n -k2,2n -k3,3n | tail -n 1
-
Kyle Berezin over 3 yearsThanks, this works on Snow Leopard (don't ask).
-
wisbucky over 2 years@shadowbq It will work with mac
sed
if you get rid of the optional curly braces:sed '/-/! s/$/_/'
(I added a space for readability.) -
wisbucky over 2 yearsIf you're wondering why you can't simply add an
_
to every line, it's because it would mess up the order ofalpha
andalpha1
.alpha1_
would come beforealpha_
, which is wrong. -
Nonoroazoro almost 2 years"sort -V" is the key.