PowerShell 中可重用的排序功能

问题描述 投票:0回答:1

我有一个包含脚本名称的字符串列表。我需要检查这些脚本的版本,以确定它们的版本是否低于最新执行的版本,并且仅按照该版本的脚本顺序执行版本号高于最新版本的脚本。我还有一个已执行脚本的字符串列表,因此为了确定最新的脚本,需要对该列表进行排序。

因此,我编写了一些代码来解析这些字符串中的版本详细信息,并希望使用相同的“函数”对两个列表进行排序 - 但我无法进行排序。当我直接调用它时,

Sort-Object
部分可以工作,但不能使用函数
Sort-Scripts
。我是 PowerShell 的新手,所以我一定忽略了一些基本的东西。但我不明白是什么。

function Get-SemVer($version) {
    $version -match '^(?<major>\d+)(\.(?<minor>\d+))?(\.(?<patch>\d+))?(\-(?<pre>[0-9A-Za-z\-\.]+))?(\+(?<build>[0-9A-Za-z\-\.]+))?$' | Out-Null
    if ($matches) {
        [PSCustomObject]@{
            Major = [int]$matches['major']
            Minor = [int]$matches['minor']
            Patch = [int]$matches['patch']
            PreReleaseLabel = [string]$matches['pre']
            BuildLabel = [string]$matches['build']
        }
    }
}

function ParseVersionDetails {
    param([string]$InputString)

    if ($InputString -match '^(?<version>.*?)_(?<sequence>\d+)_?(?<scriptname>.*)') {
        [PSCustomObject]@{
            Version = Get-SemVer $matches['version']
            Sequence = [int]$matches['sequence']
            ScriptName = $matches['scriptname']
            FullName = $InputString
        }
    }
}

function Sort-Scripts {
    process {
        @($Input) | Sort-Object -Property @{Expression={$_.Version.Major}}, @{Expression={$_.Version.Minor}}, @{Expression={$_.Version.Patch}}, @{Expression={$_.Version.PreReleaseLabel}}, @{Expression={$_.Version.BuildLabel}}, @{Expression={$_.Sequence}}
    }
}

$list = @(
    "7.9.0-dev-IRIS-Dyn_02_SomeScript",
    "7.9.0-dev-IRIS-Dyn_01_SomeScript",
    "7.9.1-prod-IRIS-Dyn+13_01_OtherScript",
    "7.8.5_02_AnotherScript",
    "7.8.5_01_AnotherScript"
)

"#### Doesn't work"
$list | ForEach-Object { ParseVersionDetails -InputString $_ } | Sort-Scripts

"####  Works"
$list | ForEach-Object { ParseVersionDetails -InputString $_ } | Sort-Object -Property @{Expression={$_.Version.Major}}, @{Expression={$_.Version.Minor}}, @{Expression={$_.Version.Patch}}, @{Expression={$_.Version.PreReleaseLabel}}, @{Expression={$_.Version.BuildLabel}}, @{Expression={$_.Sequence}}

"Done"
powershell sorting code-reuse
1个回答
0
投票

Powershell 有一个语义版本控制类型:

[semver]

(以及
[version]
用于常规(?)版本控制)

并且您不需要整个函数来排序,您只需准备一个带有

Sort-Object

参数的 splat 即可
# Evaluate a name with Approved Verbs
function ParseVersionDetails {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline, Mandatory)]
        [string]$InputString
    )
    process {
        # Check if there was a match
        if ($InputString -match '^(?<version>.*?)_(?<sequence>\d+)_?(?<scriptname>.*)') {
            
            # will valorize $version with $false of the parsing fails.   
            # otherwise it will valorize it with the parsed [semver] version number.  
            # [ref] requires the variable being created in advance, no matter if with just $null
            $version = $null
            # suppressing the boolean output.   
            $null = [semver]::TryParse($matches['version'], [ref]$version)

            [PSCustomObject]@{
                Version    = $version
                Sequence   = [int]$matches['sequence']
                ScriptName = $matches['scriptname']
                FullName   = $InputString
            }
        }
    }
}

# Splat ariable for Sort-Object .  
$SortParameters = @{ 
    Property = @{Expression = { $_.Version.Major } },
    @{Expression = { $_.Version.Minor } }, 
    @{Expression = { $_.Version.Patch } }, 
    @{Expression = { $_.Version.PreReleaseLabel } }, 
    @{Expression = { $_.Version.BuildLabel } }, 
    @{Expression = { $_.Sequence } }
}

$list = @(
    '7.9.0-dev-IRIS-Dyn_02_SomeScript',
    '7.9.0-dev-IRIS-Dyn_01_SomeScript',
    '7.9.1-prod-IRIS-Dyn+13_01_OtherScript',
    '7.8.5_02_AnotherScript',
    '7.8.5_01_AnotherScript',
    'Made.to.fail'
)

$list | ParseVersionDetails | Sort-Object @SortParameters 


'Done'
© www.soinside.com 2019 - 2024. All rights reserved.