用尾随零对字母数字字符串进行排序

时间:2019-05-06 11:00:42

标签: powershell sorting

我有一个脚本,其中包含字母数字字符串数组,例如VER11.10.00.000VER11.10.01.123VER9.09.02.050

我对此数组进行排序

[string[]] $HighestVER = $Version | Sort -Descending
foreach($element in $HighestVER) {
    Write-Host $element
}

$Version表示字符串的无序数组。 运行脚本时,结果如下:

VER9.16.00.000
VER9.15.00.000
VER9.14.00.000
VER9.13.00.000
VER11.9.00.000
VER11.8.00.000
VER11.7.00.000
VER11.6.00.000
VER11.5.00
VER11.4.00.000
VER11.3.00.016
VER11.3.00.000
VER11.2.00.000
VER11.10.00.000

如您所见,排序正在做某事,但未达到我的预期。我的预期输出是:

VER11.10.00.000
VER11.9.00.000
VER11.8.00.000
VER11.7.00.000
VER11.6.00.000
VER11.5.00
VER11.4.00.000
VER11.3.00.016
VER11.3.00.000
VER11.2.00.000
VER9.16.00.000
VER9.15.00.000
VER9.14.00.000
VER9.13.00.000

如何改进代码以匹配预期的输出?

编辑:

我无法使用[System.Version]解决此问题,因为我的版本中包含字母字符。如果我删除前三个字符VER并进行比较,那还是可以的,但是该版本的元素变得混乱了。

[string[]] $HighestVER = $Version2 | ForEach-Object { [System.Version] $_ } | Sort-Object -Descending | ForEach-Object { $_.toString() }


#[string[]] $HighestVER = $Version | Sort -Descending
foreach($element in $HighestVER) {
    $element = "VER" + $element
    Write-Host $element
}

这给了我这个输出:

VER11.10.0.0
VER11.9.0.0
VER11.8.0.0
VER11.7.0.0
VER11.6.0.0
VER11.5.0
VER11.4.0.0
VER11.3.0.16
VER11.3.0.0
VER11.2.0.0
VER9.16.0.0
VER9.15.0.0
VER9.14.0.0
VER9.13.0.0

最高版本号。用于比较和扩展版本列表(Dynamics NAV自动构建)。因此,格式不必相同。

4 个答案:

答案 0 :(得分:1)

假设变量$vers包含您提供的格式的版本数组,那么以下操作将起作用。

(($vers  -replace "VER(?<Num>.*)",'${Num}' |
  ForEach-Object {$_ -as [system.version]}) | Sort-Object -Desc) |
  Foreach-Object {
    ("VER{0}.{1}.{2:D2}.{3:D3}" -f $_.Major,$_.Minor,$_.Build,$_.Revision) -replace "\.-\d+"}

此解决方案基本上提取版本号并将其转换为[system.version]对象。可以使用Sort-Object按照您要求的方式自然地对该对象进行排序。排序完成后,将重建输出,将那些版本对象转换为字符串。

-replace运算符执行正则表达式替换。第一个从每行中删除字符串VER。第二个命令删除由强制转换添加到[system.version]的所有负整数。

最后一个Foreach-Object正在使用格式运算符(-f)格式化输出,它会加回在排序之前删除的字符串VER。然后,它使用[system.version]对象的每个部分来执行填充的串联。 {2:D2}用前导0填充版本的第三数字部分,以使其为两位数。 {3:D3}用前导0填充版本的第四个数字部分,使其成为三位数。

在进一步测试中,可以使用Lee_Dailey中的评论进行缩短,并提高效率:

$vers | Sort-Object {$_ -replace "VER(?<Num>.*)",'${Num}' -as [system.version]} -desc

答案 1 :(得分:0)

我建议使用Roman Kuzmin的$ToNatural,它可以将字符串中的所有数字即时扩展到给定的位置(20):

## source Roman Kuzmin  https://stackoverflow.com/a/5429048/6811411
$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20,"0") }) }

$HighestVER = $Version | Sort -Descending $ToNatural
$HighestVER

VER11.10.00.000
VER11.9.00.000
VER11.8.00.000
VER11.7.00.000
VER11.6.00.000
VER11.5.00
VER11.4.00.000
VER11.3.00.016
VER11.3.00.000
VER11.2.00.000
VER9.16.00.000
VER9.15.00.000
VER9.14.00.000
VER9.13.00.000

答案 2 :(得分:0)

'
VER9.16.00.000
VER9.15.00.000
VER9.14.00.000
VER9.13.00.000
VER11.9.00.000
VER11.8.00.000
VER11.7.00.000
VER11.6.00.000
VER11.5.00
VER11.4.00.000
VER11.3.00.016
VER11.3.00.000
VER11.2.00.000
VER11.10.00.000
' | ConvertFrom-Csv -Header String |
    Select-Object String, 
        @{Name='Version';Expression={[System.Version]::New($_.String.SubString(3))}} |
    Sort-Object -Descending Version | 
    Select-Object -Expand String

VER11.10.00.000
VER11.9.00.000
VER11.8.00.000
VER11.7.00.000
VER11.6.00.000
VER11.5.00
VER11.4.00.000
VER11.3.00.016
VER11.3.00.000
VER11.2.00.000
VER9.16.00.000
VER9.15.00.000
VER9.14.00.000
VER9.13.00.000

说明

  • 使用String属性创建一个单列对象列表
  • 添加一个Version(类型)列
  • 根据Version列对列表进行排序
  • String列中仅输出 原始 数据

答案 3 :(得分:0)

您可以将脚本块与sort-object一起使用。有点像另一个答案。

PS C:\users\me> $version | sort { [version]($_ -replace 'VER') } -Desc

VER11.10.00.000
VER11.9.00.000
VER11.8.00.000
VER11.7.00.000
VER11.6.00.000
VER11.5.00
VER11.4.00.000
VER11.3.00.016
VER11.3.00.000
VER11.2.00.000
VER9.16.00.000
VER9.15.00.000
VER9.14.00.000
VER9.13.00.000