You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell可复用排序函数失效问题排查

PowerShell 自定义排序函数失效问题修复

我有一组包含脚本名称的字符串列表,需要完成以下操作:

  • 检查脚本版本,筛选出版本高于已执行最新版本的脚本,并按版本对应的执行顺序运行
  • 对已执行脚本列表排序,确定其中的最新脚本

我编写了解析版本信息的代码,希望复用Sort-Scripts函数给两个列表排序,但该函数无法正常工作,直接调用Sort-Object却能得到正确结果。相关代码如下:

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"

问题原因

Sort-Scripts函数的process块中,$Input是逐元素接收管道输入的——每次process块执行时,@($Input)里只有当前处理的单个对象。对单个对象排序不会改变任何顺序,因此函数看起来完全没生效。

而直接调用Sort-Object时,它会先收集所有管道输入,再统一执行排序逻辑,所以能得到正确结果。

修复方案

修改Sort-Scripts函数,先收集所有管道输入到数组,再在end块中统一排序。有两种写法:

写法1:用begin/process/end块收集输入

function Sort-Scripts {
    begin { 
        # 初始化数组存储所有输入对象
        $allScripts = @() 
    }
    process { 
        # 逐元素添加到数组
        $allScripts += $_ 
    }
    end {
        # 对完整数组执行排序
        $allScripts | Sort-Object -Property `
            @{Expression={$_.Version.Major}},
            @{Expression={$_.Version.Minor}},
            @{Expression={$_.Version.Patch}},
            @{Expression={$_.Version.PreReleaseLabel}},
            @{Expression={$_.Version.BuildLabel}},
            @{Expression={$_.Sequence}}
    }
}

写法2:显式声明管道参数(更规范)

function Sort-Scripts {
    [CmdletBinding()]
    param(
        # 声明接收管道输入的参数
        [Parameter(ValueFromPipeline = $true)]
        $InputObject
    )
    begin { 
        $allScripts = @() 
    }
    process { 
        $allScripts += $InputObject 
    }
    end {
        $allScripts | Sort-Object -Property `
            @{Expression={$_.Version.Major}},
            @{Expression={$_.Version.Minor}},
            @{Expression={$_.Version.Patch}},
            @{Expression={$_.Version.PreReleaseLabel}},
            @{Expression={$_.Version.BuildLabel}},
            @{Expression={$_.Sequence}}
    }
}

修改后,Sort-Scripts函数就能和直接调用Sort-Object产生完全一致的排序结果,可复用给多个列表排序。

内容的提问来源于stack exchange,提问作者causa prima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 20:12:37