How to sort semantic versions in bash?

Kirby picture Kirby · Nov 2, 2016 · Viewed 7.6k times · Source

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.

Answer

glenn jackman picture glenn jackman · Nov 2, 2016

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.