jq 按版本作为字符串排序

问题描述 投票:0回答:2

我正在尝试对以下 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

有人有想法来实现这个吗? 🙂

json sorting version jq
2个回答
11
投票

将每个分量转换为数字,然后对整数数组进行排序。

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
投票

此功能允许您使用完整的语义版本控制 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]]
  1. sub("\\+.*$"; "")
    删除任何最终的元数据,不参与比较。
  2. 如果存在
  3. 预发布后缀
    capture("^(?<v>[^-]+)(?:-(?<p>.*))?$") | [.v, .p // empty]
    将字符串拆分为类似
    ["x.y.z"]
    ["x.y.z", "pre.release"] 的数组。
  4. map(split(".") | map(opt(tonumber)))
    通过
    .
    进一步拆分这些元素,并在可能的情况下将“标识符”转换为数字(以数字方式排序)。
  5. .[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" }
]
© www.soinside.com 2019 - 2024. All rights reserved.