我有一个包含脚本名称的字符串列表。我需要检查这些脚本的版本,以确定它们的版本是否低于最新执行的版本,并且仅按照该版本的脚本顺序执行版本号高于最新版本的脚本。我还有一个已执行脚本的字符串列表,因此为了确定最新的脚本,需要对该列表进行排序。
因此,我编写了一些代码来解析这些字符串中的版本详细信息,并希望使用相同的“函数”对两个列表进行排序 - 但我无法进行排序。当我直接调用它时,
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 有一个语义版本控制类型:
[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'