Сортировать буквенно-цифровую строку с конечными нулями - PullRequest
1 голос
/ 06 мая 2019

У меня есть скрипт, который содержит массив буквенно-цифровых строк, таких как VER11.10.00.000, VER11.10.01.123 и VER9.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

Как я могу улучшить свой код, чтобы он соответствовал ожидаемому результату?

Edit:

Я не могу решить эту проблему с [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 ]

1 голос
/ 06 мая 2019

Если переменная $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
0 голосов
/ 06 мая 2019

Вы можете использовать блок скрипта с 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
0 голосов
/ 06 мая 2019
'
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
0 голосов
/ 06 мая 2019

Я предлагаю использовать $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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...