如何在bash中对语义版本进行排序?
Posted
技术标签:
【中文标题】如何在bash中对语义版本进行排序?【英文标题】:How to sort semantic versions in bash? 【发布时间】:2017-03-16 09:58:09 【问题描述】:我想对语义版本进行排序 (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
有一些现有的方法吗?
附言
按照常识,应该遵循这个架构:
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.
附言
Semver 2.0 不支持补丁,但它是必需的。
【问题讨论】:
“-patch”要求使得它与 semver 不兼容,所以你不应该调用这个 semver。另一方面,semver 不支持第三方补丁,它仅用于官方发布(在补丁的情况下,源开发人员应在 PATCH 部分的数字上加 1)。如果你真的在推,或许可以在版本结束后用+metadata来完成。 是的,这是真的。它不支持“补丁”类型的版本。关于元数据 - 包管理器不考虑元数据。他们切断了它。我说的是作曲家,确切地说。所以,可能会有问题。 意思是,它会产生意想不到的结果,你尝试获得1.0.0版本有两个版本,例如:1.0.0和1.0.0+super-patch。 【参考方案1】:| 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
【讨论】:
【参考方案2】: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。
【讨论】:
【参考方案3】:你可以使用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
【讨论】:
如果有候选发布版本,例如 2.12-rc1 将在 2.12 之后排序,而它应该在 before 之前进行排序. 非常感谢这样的排序能力。它有助于对正确的 semver 版本控制进行排序(虽然我不使用后缀,例如 rc、alpha)。我从 git 获取最大版本的完整命令如下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
谢谢,这适用于雪豹(不要问)。【参考方案4】:
如果您使用的是 gplv2 (native osx) 工具,除非使用 gsed,否则 @Glenn Jack 的答案将不起作用。
这个原生 awk 命令可以替代。
| awk ' if ($1 ~ /-/) print; else print $0"_" ; ' |sort -rV | sed 's/_$//'
【讨论】:
【参考方案5】:curl -s https://api.github.com/repos/glpi-project/glpi/releases | jq --raw-output '.[] | .tag_name' | sed '/-/!s/$/_/' | sort -V | sed 's/_$//'
这不正确显示版本。
【讨论】:
【参考方案6】:好吧,我们可以通过在字符串末尾为不包含连字符的行添加一个虚拟字符来欺骗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
下划线按词法排序在连字符之后。这就是诀窍。
【讨论】:
是的。 :) 那么,为什么要添加这个? :) 嗯,因为您没有向我们展示您的预期输出? 对不起,如果不清楚。所以,我考虑过 semver,它没有补丁...... :( 如果您的命令将对 RC 和 beta 进行排序,它可以是没有补丁的问题的答案。 这在macos下可能会失败,你应该使用gsed以上是关于如何在bash中对语义版本进行排序?的主要内容,如果未能解决你的问题,请参考以下文章