json jq按版本作为字符串排序

jgwigjjp  于 2023-03-20  发布在  其他
关注(0)|答案(2)|浏览(130)

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

我目前可以做部分工作,它只适用于简单的情况(所有版本的部件major/minor/bug具有相同的位数)。
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

有人有办法实现这个吗?🙂

hyrbngr7

hyrbngr71#

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

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"
  }
]
zte4gxcn

zte4gxcn2#

这允许您使用包括-pre.release后缀在内的完整Semantic Versioning 2.0排序。

jq_semver_cmp='
def opt(f):
    . as $in | try f catch $in;
def semver_cmp:
    sub("\\+.*$"; "")
  | index("-") as $i
  | [.[:$i], if $i != null then .[$i+1:] else empty end]
  | 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. index("-") as $i查找表示预发行后缀的短划线-的第一个位置。
    我没有使用split("-"),因为后面允许使用破折号,我不想以后使用join("-")
  3. [.[:$i], if $i != null then .[$i+1:] else empty end]x.y.z放入数组中,如果找到-,则将后缀放在它旁边。
  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" }
]

相关问题