r3p*_*ica 2 sorting powershell version-numbering
所以,我有一个看起来像这样的版本列表:
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
Run Code Online (Sandbox Code Playgroud)
问题是,它们的顺序不正确。我是 Powershell 的新手,所以我在尝试对它们进行排序时遇到了一些问题。我试图这样做:
$tags = git tag
$versions = $tags | %{ new-object System.Version ($_) } | sort
Run Code Online (Sandbox Code Playgroud)
但我收到此错误:
新对象:使用“1”个参数调用“.ctor”的异常:“版本字符串部分太短或太长。” 在行:1 字符:24 + $versions = $tags | %{ 新对象 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 " "
}
}
Run Code Online (Sandbox Code Playgroud)
这种工作,但所有标签似乎都被控制台记录,它显示了这一点:
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
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,那里有一些我不想要的。具体来说:
1.6.0
changeDeliveryFieldAccess
orders/autoComplete
returns/autoComplete
save-lines-dates
services/serviceDetails
tile-colours
users/confirmation
v.2.7.1
Run Code Online (Sandbox Code Playgroud)
一旦这些从我的列表中被清除,那么顺序就是正确的:)
所以我尝试了另一种希望更好的解决方案:
$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 " "
$tags |
Where-Object { $_.Substring(1) -as [version] } |
Sort-Object { [version] $_.Substring(1) }
foreach($tag in $tags) {
write-host "$($tag) is ok"
}
Run Code Online (Sandbox Code Playgroud)
我不确定我这样做是否正确,但这是上述代码的输出:
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
Run Code Online (Sandbox Code Playgroud)
tl;博士:
您后来指出您的$tags数组还包含其他非版本字符串,因此必须过滤掉这些字符串:
$sortedVersionTags = $tags |
Where-Object { $_.Substring(1) -as [version] } |
Sort-Object { [version] $_.Substring(1) }
Run Code Online (Sandbox Code Playgroud)
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) }
Run Code Online (Sandbox Code Playgroud)
[version]是 PowerShell 中内置的类型加速器(简称),指的是[System.Version]. [1]
您可以简单地将字符串强制转换为[version],这比使用 更简洁、更快New-Object。
Sort-Object通过脚本块 ( )接受一个表达式,{ ... }而不是一个固定的属性来排序;在脚本块内,$_指的是给定的输入对象;$_.Substring(1)只需删除第一个字符 (the v)。
Sort-Object仍然输出原始字符串- 排序。使用您的样本输入,上述收益(注意v2.10.0after排序的正确性v2.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
Run Code Online (Sandbox Code Playgroud)
如果您更愿意输出System.Version实例而不是输入字符串,命令会变得更简单(PSv3+ 语法):
[version[]] $tags.Substring(1) | Sort-Object
Run Code Online (Sandbox Code Playgroud)
如果有可能并非所有包含的字符串都$tags可以通过这种方式转换(由于没有v<version>格式),请使用以下(PSv4+ 语法):
# Reports non-convertible lines as non-terminating errors, but processes all others.
$tags.ForEach({ [version] $_.Substring(1) }) | Sort-Object
Run Code Online (Sandbox Code Playgroud)
这种方法确保遇到无法转换的字符串不会破坏整个命令:
那些可以转换的是, 和 是输出。
那些不能转换的会导致打印到控制台的错误,也会在$Error之后的自动收集中反映出来。您可以使用2>$null.
[1] 通常,PowerShell 允许您省略System.类型名称中的前缀。
| 归档时间: |
|
| 查看次数: |
616 次 |
| 最近记录: |