gpt4 book ai didi

powershell - 正确排序包含版本号的列表

转载 作者:行者123 更新时间:2023-12-01 19:34:58 27 4
gpt4 key购买 nike

所以,我有一个看起来像这样的版本列表:

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 : Exception calling ".ctor" with "1" argument(s): "Version string portion was too short or too long." At line:1 char:24 + $versions = $tags | %{ new-object System.Version ($_) } | sort + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

谁能帮忙?


更新

我使用了一种如下所示的解决方案:

$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

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


更新 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] }仅将那些字符串通过 可转换[version] ( System.Version ) 对象 - -as [version] - 删除 v 后一开始( .Substring(1) ;忽略删除 v 是您最初的问题); -as运算符要么返回一个成功转换的值,要么返回 $null .

  • Sort-Object然后将过滤后的标签按版本号排序,这会产生正确的顺序 - 请参阅下一节了解说明。

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


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]是内置于 PowerShell 中的类型加速器(简称),指的是 [System.Version] .[1]

  • 您可以简单地将字符串转换[version] , 这比使用 New-Object 更简洁和快速.

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

    • 请注意,该表达式仅暂时使用,用于排序Sort-Object仍然输出 原始字符串 - 已排序。

使用您的示例输入,上述产量(注意 v2.10.0v2.9.0 之后如何正确排序,词法排序不会出现这种情况):

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

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

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

如果$tags 中可能没有所有 个字符串可以这样转换(由于没有v<version>格式),使用以下(PSv4+语法):

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

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

  • 那些可以被转换的,并且被输出。

  • 那些不能被转换的会导致打印到控制台的错误,也会反射(reflect)在自动$Error之后收集。您可以使用 2>$null 抑制控制台输出.


[1] 通常,PowerShell 允许您省略 System.类型名称中的前缀。

关于powershell - 正确排序包含版本号的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55048174/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com