簡體   English   中英

正確排序包含版本號的列表

[英]Sort a list that contains version numbers properly

因此,我有一個看起來像這樣的版本列表:

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行:char:24 + $ versions = $ tags | %{新對象System.Version($ _)} | 排序+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + 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通過腳本塊( { ... } )接受一個表達式來代替要進行排序的固定屬性; 在腳本塊中, $_指向給定的輸入對象; $_.Substring(1)只是刪除第一個字符( v )。

    • 請注意,出於排序目的,該表達式僅臨時使用; Sort-Object仍輸出原始字符串 -已排序。

使用示例輸入,上面的結果(注意v2.10.0如何在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

如果您希望輸出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

這種方法確保遇到無法轉換的字符串不會破壞整體命令

  • 可以轉換的 ,並輸出。

  • 那些無法轉換的將導致打印到控制台的錯誤,並且此后還將反映在自動$Error集合中。 您可以使用2>$null抑制控制台輸出。


[1]通常,PowerShell允許您省略System. 類型名稱中的前綴。

排序字符串中任何長度的數字的更通用方法是Roman Kuzmin的$ ToNatural

如果將其存儲在腳本/配置文件中:

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

您可以簡單地使用:

$tags | Sort-Object $ToNatural

v1.1.0
v1.2.0
v1.3.0
...
v2.7.0
v2.8.0
v2.9.0
v2.10.0
v2.11.0
v2.12.0

我相信,如果您希望對它們進行排序沒有問題,則需要將這些字符串正確地解析為版本對象。


$tags = @(
    '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'
)


 #----------------------------------------------------------------------------# 
 #     Parse Will Fail As 'v' In String is Not Valid Semantic Versioning      # 
 #----------------------------------------------------------------------------# 
$tags | % { 
    $tag = $_
    $version = [version]::new()
    if ([version]::TryParse($tag, [ref]$version))
    {
        $version
    }
    else 
    {"ParseFailed--$($tag)"}

} | Sort-Object


 #----------------------------------------------------------------------------# 
 #                        Parsing String Successfully                         # 
 #----------------------------------------------------------------------------# 
$tags | % { 
    $tag = $_ -replace '[a-zA-Z]'
    $version = [version]::new()
    if ([version]::TryParse($tag, [ref]$version))
    {
        $version
    }
    else 
    {"ParseFailed--$($tag)"}

} | Sort-Object


如果還想將其用作2.1.0類型的字符串,則可以對返回的對象使用ToString()

問題是版本字符串中不允許使用“ v”。 如果先將其刪除,則可以正確排序:

$tags | Sort-Object {[Version]($_ -replace "[a-zA-Z]","")}

請注意,這並不是真正刪除“ v”(它會創建一個沒有它的副本),並且仍然會出現在輸出中:

v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM