在powershell中使用python风格的元组进行比较



我正在尝试将此python模块移植到powershell

def str_to_tuple(s):
'''        @source kindall at stackoverflow          
http://stackoverflow.com/a/11887825/3447669
'''
return tuple(map(int, (s.split("."))))

最终的结果是,我将我的python代码移植到powershell中,以便在windows服务器上使用,因为团队的其他成员不了解python。

我有一个python脚本,可以比较两个应用程序版本号(即1.2.33和1.2.34)。上面的模块给了我一个元组,我可以在两个版本#s>或<之间进行比较;。

我专门测试在运行时提供的$appVersion -lt $myVersionString,所以-eq对我们的脚本来说不是一个足够的测试。

我曾尝试使用$str.split()将字符串元素放入数组中,但比较不起作用,而且我不想循环遍历每个数组来比较每个项,因为版本号可以是不同的长度。。。

Examples of lengths
1.2 
2.3.4 
2.3.44

感谢您的指导。

@Lee_Dayey指出,最简单的解决方案是将字符串强制转换为类型System.Version:

PS/home/me>$s1='1.2.3'PS/hom/me>$s2='1.19.2'PS/home>[版本]$v1=$s1PS/home>[版]$v2=$s2PS-home/me>$v1主要次要内部版本修订----------------------1 2 3-1PS/home/me>$v2主要次要版本修订----------------------1 19 2-1PS/home/me>$v1-gt$v2错误PS/home/me>$v2-gt$v1True

我刚刚在Linux上的PowerShell Core 6.1中测试了它,它运行得很好,所以我希望它能在Mac OS上的PowerShell核心中运行;X也是。

然而,您也可以使用与Python中使用的方法完全相同的方法:从字符串创建元组。

PS/home/me>$s1='1.2.3'PS/hom/me>$s2='1.19.2'PS/home>[int[]]$v1=$s1.拆分('.'ple[int,int,int]'$a2PS/home/me>$t1第1项第2项第3项长度--------------------1 2 3 3PS/home/me>$t2第1项第2项第3项长度--------------------1 19 2 3PS/home/me>$t1-gt$t2错误PS/home/me>$t2-gt$t1True

请注意,拆分字符串会得到一个字符串数组,因此必须将其强制转换为整数数组,否则比较将无法正常工作(因为将使用字符串比较而不是数字比较)。

还要注意,类型定义(Tuple[<type>,<type>,...])中的元素数量必须与创建元组的数组中的元素数相匹配。这个答案显示了一个可重用的函数,用于从任意数组创建元组:

function New-Tuple {
Param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true
)]
[ValidateCount(2,20)]
[array]$Values
)
Process {
$types = ($Values | ForEach-Object { $_.GetType().Name }) -join ','
New-Object "Tuple[$types]" $Values
}
}

这样你就可以改变

$t1 = New-Object 'Tuple[int,int,int]' $a1
$t2 = New-Object 'Tuple[int,int,int]' $a2

$t1 = New-Tuple $a1
$t2 = New-Tuple $a2

不过,要注意,比较元组需要它们具有相同数量的元素,否则比较将失败:

PS/home/me>$s3='1.19.2.1'PS/hom/me>[int[]]$a3=$s3.拆分('.')PS/home/me>1$t3=新对象'Tuple[int,int,int,int]'$a3PS-home/me>$t3-gt$t2无法将"(1,19,2,1)"与"(1、19,2)"进行比较。错误:"无法转换"(1,19,2)"类型的值">System.Tuple`3[[System.Int32,System.Private.CoreLib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=7cec85d7bea7798e],[System.Int32,System.Private.CoreLib,版本=4.0.0.0,区域性=中性,PublicKeyToken=7ec85d7bea7798e],[System.Int32,System.Private.CoreLib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=7cec85d7bea7798e]]"到类型">System.Tuple`4[System.Int32,System.Int32,System.Int32,System.Int32]".">在行:1个字符:1+$t3-gt$t2+~~~~~~~~~~~+CategoryInfo:InvalidOperation:(:)[],RuntimeException+FullyQualifiedErrorId:ComparisonFailure

因此,您必须确保版本元组始终具有相同的长度,例如,将0元素附加到数组中,然后从结果中拾取前4个元素:

[int[]]$a = ('1.2'.Split('.') + (0, 0, 0, 0))[0..3]
$t = New-Object 'Tuple[int,int,int,int]' $a

[Version]类型加速器没有这个问题,因为它创建了相同类型的对象,版本字符串中缺少的数字会自动填充值-1

PS/home/me>[版本]'1.2'主要次要版本修订----------------------1 2-1-1PS/home/me>[版本]'1.2.3’主要次要版本修订----------------------1 2 3-1PS/home/me>[版本]'1.2.3.4'主要次要版本修订----------------------1 2 3 4

已通知Donald.M&Lee_Dayey在评论中使用PoshSematicVersion[version]解决了该解决方案(发现与PowerShell Core不兼容)

这是我在发布解决方案之前开发的解决方案,也许这可以与PowerShell Core一起使用——尽管不确定且未经测试。不管你愿不愿意,这是我的解决方案。

然而,str_to_tuple()函数是一个与原始函数非常相似的单行函数!从技术上讲,返回的不是元组,而是[System.Array],但可能存在类型元组。

(注意:具有负版本控制的未知行为-甚至存在。)

function str_to_tuple($s) {
return (($s.split(".") | ForEach-Object {([int]::parse($_))}))
}
# returns 1 if left ($lhs) is greater than right
# returns -1 if right ($rhs) is greater than left
# returns 0 if both right and left versions equal
function comp_vers {
Param([Parameter(Position=0,Mandatory=$true)]$lhs, [Parameter(Position=1,Mandatory=$true)]$rhs)
$min = [math]::Min($lhs.count,$rhs.count)
for($i=0; $i -lt $min; $i++) {
if ($lhs[$i] -eq $rhs[$i]) { continue }
if ($lhs[$i] -gt $rhs[$i]) { return 1 }
else { return -1 }
}
if ($lhs.count -eq $rhs.count) { return 0 }
# Section 2 - compares version numbers further (for example, 1.1 versus 1.1.0.0 - should be equal)
$max = [math]::Max($lhs.count,$rhs.count)
$is_lhs_high = ($l.count -eq $max)
for($i = $min; $i -lt $max; $i++) {
if ($is_lhs_high) {
if ($lhs[$i] -gt 0) { return 1 }
} else {
if ($rhs[$i] -gt 0) { return -1 }
}
}
return 0
}
function vers_output($comp) {
Switch($comp) {
1 { " > " }
0 { " = " }
-1 { " < " }
}
}
$tuple = str_to_tuple("1.1")
$tuple2 = str_to_tuple("1.1.0.0")
$tuple3 = str_to_tuple("3.3")
$tuple4 = str_to_tuple("2.2.2")
$tuple5 = str_to_tuple("2.2.2.0.1")
vers_output(comp_vers $tuple $tuple)    # 1.1 = 1.1
vers_output(comp_vers $tuple2 $tuple)   # 1.1.0.0 = 1.1
vers_output(comp_vers $tuple $tuple3)   # 1.1 < 3.3
vers_output(comp_vers $tuple3 $tuple4)  # 3.3 > 2.2.2
vers_output(comp_vers $tuple4 $tuple5)  # 2.2.2 < 2.2.2.0.1

最新更新