对包含版本号的列表进行正确排序

2023-12-01

所以,我有一个版本列表,如下所示:

v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
v1.7.0
v1.8.0
v1.9.0
v2.0.0
v2.1.0
v2.10.0
v2.11.0
v2.12.0
v2.2.0
v2.3.0
v2.4.0
v2.5.0
v2.6.0
v2.7.0
v2.8.0
v2.9.0

问题是,它们的顺序不正确。 我是 Powershell 新手,因此在尝试对它们进行排序时遇到了一些问题。 我尝试这样做:

$tags = git tag
$versions = $tags | %{ new-object System.Version ($_) } | sort

但我收到这个错误:

new-object :使用“1”个参数调用“.ctor”时出现异常:“版本字符串部分太短或太长。” 行:1 字符:24 + $版本= $标签| %{ 新对象 System.Version ($_) } |种类 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [New-Object],MethodInitationException +FullyQualifiedErrorId:ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

有人可以帮忙吗?


Update

我使用了如下解决方案之一:

$location = Get-Location
$path = $location.tostring() + "\CHANGELOG.md"
$tags = git tag
$i = 0

Clear-Content $path
Add-Content $path "Change Log"
Add-Content $path "=========="
Add-Content $path " "

$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20) }) }
$tags | Sort-Object $ToNatural

foreach($tag in $tags) 
{
    if (-NOT ($tag -match "v(\d+\.)(\d+\.)(\*|\d+)")) { continue }
    $i = $i + 1
    if ($i -eq 0) { continue }
    $tag
    If ($i -gt 0) {
        $previous = $tags[$i - 1]

        Add-Content $path " "
    }
}

这种方法可行,但所有标签似乎都已控制台记录,并且显示如下:

1.6.0
changeDeliveryFieldAccess
orders/autoComplete
returns/autoComplete
save-lines-dates
services/serviceDetails
tile-colours
users/confirmation
v0.1
v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
v1.7.0
v1.8.0
v1.9.0
v2.0.0
v2.1.0
v2.2.0
v2.3.0
v2.4.0
v2.5.0
v2.6.0
v2.7.0
v2.8.0
v2.9.0
v2.10.0
v2.11.0
v2.12.0
v.2.7.1

正如你所看到的,其中有一些我不想要的。具体来说:

1.6.0
changeDeliveryFieldAccess
orders/autoComplete
returns/autoComplete
save-lines-dates
services/serviceDetails
tile-colours
users/confirmation
v.2.7.1

一旦这些从我的列表中清除,那么顺序就会正确:)


Update 2

所以我尝试了另一种希望更好的解决方案:

$location = 获取位置 $path = $location.tostring() + "\CHANGELOG.md" $tags = git 标签 $i = 0

Clear-Content $path
Add-Content $path "#Change Log"
Add-Content $path "=========="
Add-Content $path " "

$tags |
  Where-Object { $_.Substring(1) -as [version] } |
   Sort-Object { [version] $_.Substring(1) }

foreach($tag in $tags) {
    write-host "$($tag) is ok"
}

我不确定我这样做是否正确,但这是上面代码的输出:

1.6.0 is ok
changeDeliveryFieldAccess is ok
orders/autoComplete is ok
returns/autoComplete is ok
save-lines-dates is ok
services/serviceDetails is ok
tile-colours is ok
users/confirmation is ok
v.2.7.1 is ok
v0.1 is ok
v1.1.0 is ok
v1.2.0 is ok
v1.3.0 is ok
v1.4.0 is ok
v1.5.0 is ok
v1.7.0 is ok
v1.8.0 is ok
v1.9.0 is ok
v2.0.0 is ok
v2.1.0 is ok
v2.10.0 is ok
v2.11.0 is ok
v2.12.0 is ok
v2.2.0 is ok
v2.3.0 is ok
v2.4.0 is ok
v2.5.0 is ok
v2.6.0 is ok
v2.7.0 is ok
v2.8.0 is ok
v2.9.0 is ok

tl;dr:

您后来表示您的$tags数组还包含其他,非版本字符串,所以这些必须是过滤掉:

$sortedVersionTags = $tags |
  Where-Object { $_.Substring(1) -as [version] } |
    Sort-Object { [version] $_.Substring(1) }
  • Where-Object { $_.Substring(1) -as [version] }只传递那些字符串可以转换 to [version] (System.Version) 对象 --as [version]- 删除后v在开始时(.Substring(1);忽略删除v是你最初的问题);这-as运算符返回成功​​转换的值或$null.

  • Sort-Object然后对过滤后的标签进行排序作为版本号,这会产生正确的顺序 - 请参阅下一节的解释。

  • $sortedVersionTags然后仅接收原始形式的版本标签(如v-前缀字符串),正确排序。


The v版本号中的前缀会阻止它们转换为[System.Version]实例;只需首先将其删除(不是从输入本身中删除;只是暂时删除,用于创建版本信息对象,例如,v1.1.0 -> 1.1.0).

此外,您的命令可以简化:

# $tags is an array of lines, as output by `git tag`
$tags | Sort-Object { [version] $_.Substring(1) }
  • [version] is a type accelerator (shorter name) built into PowerShell that refers to [System.Version].[1]

  • 您可以简单地cast一个字符串到[version],这比使用更简洁、更快New-Object.

  • Sort-Object接受一个表达,通过脚本块({ ... }),代替作为排序依据的固定属性;在脚本块内,$_指的是给定的输入对象;$_.Substring(1)只需删除第一个字符(v).

    • 请注意,该表达式仅用于暂时地, 为了...的目的sorting; Sort-Object仍然输出原始字符串- 排序。

根据您的示例输入,上述产量(注意如何v2.10.0之后正确排序v2.9.0,情况并非如此lexical排序):

v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
v1.7.0
v1.8.0
v1.9.0
v2.0.0
v2.1.0
v2.2.0
v2.3.0
v2.4.0
v2.5.0
v2.6.0
v2.7.0
v2.8.0
v2.9.0
v2.10.0
v2.11.0
v2.12.0

如果你愿意output System.Version实例该命令不再是输入字符串,而是变得更加简单(PSv3+ 语法):

[version[]] $tags.Substring(1) | Sort-Object

如果有可能不all包含在的字符串$tags可以这样转换(由于没有v<version>格式),使用以下(PSv4+ 语法):

# Reports non-convertible lines as non-terminating errors, but processes all others.
$tags.ForEach({ [version] $_.Substring(1) }) | Sort-Object

这种方法确保遇到无法转换的字符串不会破坏整个命令:

  • 那些can被转变are、 和 均输出。

  • 那些cannot被转换将导致打印到控制台的错误,并且也会反映在自动$Error之后收集。您可以使用以下命令抑制控制台输出2>$null.


[1] Generally, PowerShell allows you to omit the System. prefix in type names.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对包含版本号的列表进行正确排序 的相关文章

随机推荐