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.
Handling patches can use he same strategy: replace the hyphen with an underscore, and restore it after sorting
cat << VERSIONS | sed '/-/!{s/$/_/;}; s/-patch/_patch/' | sort -V | sed 's/_$//; s/_patch/-patch/'
v1.4.0-alpha
v1.4.0-alpha1
v1.4.0-beta
v1.4.0-patch
v1.4.0-patch2
v1.4.0-patch9
v1.4.0-patch10
v1.4.0-rc1
v1.4.0
v1.5.0-alpha
v1.5.0-alpha2
v1.5.0-alpha1
v1.5.0-beta
v1.5.0-patch
v1.5.0-patch1
v1.5.0-beta2
v1.5.0
VERSIONS
outputs
v1.4.0-alpha
v1.4.0-alpha1
v1.4.0-beta
v1.4.0-rc1
v1.4.0
v1.4.0-patch
v1.4.0-patch2
v1.4.0-patch9
v1.4.0-patch10
v1.5.0-alpha
v1.5.0-alpha1
v1.5.0-alpha2
v1.5.0-beta
v1.5.0-beta2
v1.5.0
v1.5.0-patch
v1.5.0-patch1