我正在尝试对以下 json 响应进行排序以选择最新版本:
[
{
"TagVersion": "1.0.11"
},
{
"TagVersion": "1.1.8"
},
{
"TagVersion": "1.0.10",
},
{
"TagVersion": "1.0.9",
},
{
"TagVersion": "1.0.77"
}
]
正确的排序应该是:
{
"TagVersion": "1.0.9",
},
{
"TagVersion": "1.0.10",
},
{
"TagVersion": "1.0.11"
},
{
"TagVersion": "1.0.77"
},
{
"TagVersion": "1.1.8"
}
我目前能够完成部分工作。它适用于简单的情况(所有版本部分主要/次要/错误具有相同的位数)。
jq -r [.[]]|max_by(.TagVersion|split(".") | map(tonumber)
在我看来,最好的方法应该是在每个部分上添加一个乘法。示例:
# With condition than every "part" as a maximum of 2 digits. It won't work with 3 digits
# Version 1.23.87
1 * 1000 + 23 * 10 + 87 = 1317
# Version 3.0.0
1 * 1000 + 0 * 10 + 0 = 3000
# Version 1.89.78
1 * 1000 + 89*10 + 78 = 1968
有人有想法来实现这个吗? 🙂
将每个分量转换为数字,然后对整数数组进行排序。
jq 'sort_by(.TagVersion|split(".")|map(tonumber))'
输出:
[
{
"TagVersion": "1.0.9"
},
{
"TagVersion": "1.0.10"
},
{
"TagVersion": "1.0.11"
},
{
"TagVersion": "1.0.77"
},
{
"TagVersion": "1.1.8"
}
]
此功能允许您使用完整的语义版本控制 2.0 排序,包括
-pre.release
后缀。
jq_semver_cmp='
def opt(f):
. as $in | try f catch $in;
def semver_cmp:
sub("\\+.*$"; "")
| capture("^(?<v>[^-]+)(?:-(?<p>.*))?$") | [.v, .p // empty]
| map(split(".") | map(opt(tonumber)))
| .[1] |= (. // {});'
jq "$jq_semver_cmp"'sort_by(.TagVersion|semver_cmp)'
由于它使用了一些技巧,我可以解释一下。一般来说,
semver_cmp
函数将版本字符串切入一个 2 级数组,该数组 jq
可以根据需要进行本机排序。数组看起来像这样:
"0.1.0": [[0,1,0],{}]
"0.1.0-alpha.2": [[0,1,0],["alpha", 2]]
sub("\\+.*$"; "")
删除任何最终的元数据,不参与比较。,
capture("^(?<v>[^-]+)(?:-(?<p>.*))?$") | [.v, .p // empty]
将字符串拆分为类似 ["x.y.z"]
或 ["x.y.z", "pre.release"]
的数组。map(split(".") | map(opt(tonumber)))
通过 .
进一步拆分这些元素,并在可能的情况下将“标识符”转换为数字(以数字方式排序)。.[1] |= (. // {})
是一个小技巧,它为没有后缀的普通版本字符串添加一个空对象作为第二个元素。 对象在数组之后排序,这就是我们这里所需要的。整理完毕后,输入如下:
[
{ "TagVersion": "1.0.11" },
{ "TagVersion": "1.0.11-alpha.2" },
{ "TagVersion": "1.0.11-alpha" }
]
正确地会像这样结束——在预发布之后排序普通版本。
[
{ "TagVersion": "1.0.11-alpha" },
{ "TagVersion": "1.0.11-alpha.2" },
{ "TagVersion": "1.0.11" }
]