如何在 bash 中对语义版本进行排序?

How to sort semantic versions in bash?

我想对语义版本进行排序(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

以适当的方式。例如,作为 version_compare() does in PHP(它不是直接的,但可以用于此)。

当然,sort -V|--version-sort在这里不起作用。

$ echo 1.0 1.0-alpha | tr ' ' "\n" | sort --version-sort
1.0
1.0-alpha

有没有现成的方法?

P.S.

按常理来说,应该遵循这个模式:

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 不支持补丁,但它是必需的。

好吧,我们可以通过在字符串末尾为不包含连字符的行添加一个虚拟字符来欺骗 sort -V

$ 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

下划线在 连字符之后进行词法排序。这就是诀窍。

1. bash

中的自定义脚本

我实现了my own solution

代码有点难看,但是可以用。

安装

$ 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。使用 semver in node

注意:所有版本都必须遵循特定的模式,它不支持“补丁”。

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
semver@5.3.0 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。在控制台

中使用 PHP 和 version_compare()

此外,PHP 原生 version_compare()(当然使用 PHP :))here.

curl -s https://api.github.com/repos/glpi-project/glpi/releases | jq --raw-output '.[] | .tag_name' |  sed '/-/!{s/$/_/}' | sort -V | sed 's/_$//'

这不正确显示版本。

如果您使用的是 gplv2(本机 osx)工具,除非使用 gsed,@Glenn Jack 的回答将不起作用。

这个原生awk命令可以替代。

| awk '{ if ( ~ /-/) print; else print [=10=]"_" ; }' |sort -rV | sed 's/_$//'

您可以使用Linux排序:

$ 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

来源:https://gist.github.com/loisaidasam/b1e6879f3deb495c22cc#gistcomment-1613531

| 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