PowerShell中的三元运算符
据我所知,PowerShell似乎没有所谓的三元运算符的内置expression式。
例如,在支持三元运算符的C语言中,我可以写如下的东西:
<condition> ? <condition-is-true> : <condition-is-false>;
如果在PowerShell中并不存在,那么最好的方法是什么(即易于阅读和维护)来实现相同的结果?
$result = If ($condition) {"true"} Else {"false"}
其他一切都是偶然的复杂性,因此要避免。
用于或作为一个expression式,而不仅仅是一个赋值,将其包装在$()
,因此:
write-host $(If ($condition) {"true"} Else {"false"})
我能够想出的最接近的Powershell构造是:
. ({'condition is false'},{'condition is true'})[$condition]
通过这个PowerShell博客文章 ,您可以创build一个别名来定义一个?:
操作符:
set-alias ?: Invoke-Ternary -Option AllScope -Description "PSCX filter alias" filter Invoke-Ternary ([scriptblock]$decider, [scriptblock]$ifTrue, [scriptblock]$ifFalse) { if (&$decider) { &$ifTrue } else { &$ifFalse } }
像这样使用它:
$total = ($quantity * $price ) * (?: {$quantity -le 10} {.9} {.75})
我也在寻找更好的答案,虽然Edward的post中的解决scheme是“好的”,但是我在这篇博文中提出了更为自然的解决scheme
简短而甜美:
# --------------------------------------------------------------------------- # Name: Invoke-Assignment # Alias: = # Author: Garrett Serack (@FearTheCowboy) # Desc: Enables expressions like the C# operators: # Ternary: # <condition> ? <trueresult> : <falseresult> # eg # status = (age > 50) ? "old" : "young"; # Null-Coalescing # <value> ?? <value-if-value-is-null> # eg # name = GetName() ?? "No Name"; # # Ternary Usage: # $status == ($age > 50) ? "old" : "young" # # Null Coalescing Usage: # $name = (get-name) ? "No Name" # --------------------------------------------------------------------------- # returns the evaluated value of the parameter passed in, # executing it, if it is a scriptblock function eval($item) { if( $item -ne $null ) { if( $item -is "ScriptBlock" ) { return & $item } return $item } return $null } # an extended assignment function; implements logic for Ternarys and Null-Coalescing expressions function Invoke-Assignment { if( $args ) { # ternary if ($p = [array]::IndexOf($args,'?' )+1) { if (eval($args[0])) { return eval($args[$p]) } return eval($args[([array]::IndexOf($args,':',$p))+1]) } # null-coalescing if ($p = ([array]::IndexOf($args,'??',$p)+1)) { if ($result = eval($args[0])) { return $result } return eval($args[$p]) } # neither ternary or null-coalescing, just a value return eval($args[0]) } return $null } # alias the function to the equals sign (which doesn't impede the normal use of = ) set-alias = Invoke-Assignment -Option AllScope -Description "FearTheCowboy's Invoke-Assignment."
这使得它可以很容易地做到这一点(更多的博客文章):
$message == ($age > 50) ? "Old Man" :"Young Dude"
由于分配值时通常使用三元运算符,因此应该返回一个值。 这是可以工作的方式:
$var=@("value if false","value if true")[[byte](condition)]
愚蠢的,但工作。 也可以使用这种结构快速将int转换为另一个值,只需添加数组元素并指定一个返回基于0的非负值的expression式即可。
由于我已经使用了很多次,并没有在这里列出,所以我会加上我的作品:
$var = @{$true="this is true";$false="this is false"}[1 -eq 1]
最丑的!
有点源头
这是另一种自定义函数方法:
function Test-TernaryOperatorCondition { [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true, Mandatory = $true)] [bool]$ConditionResult , [Parameter(Mandatory = $true, Position = 0)] [PSObject]$ValueIfTrue , [Parameter(Mandatory = $true, Position = 1)] [ValidateSet(':')] [char]$Colon , [Parameter(Mandatory = $true, Position = 2)] [PSObject]$ValueIfFalse ) process { if ($ConditionResult) { $ValueIfTrue } else { $ValueIfFalse } } } set-alias -Name '???' -Value 'Test-TernaryOperatorCondition'
例
1 -eq 1 |??? 'match' : 'nomatch' 1 -eq 2 |??? 'match' : 'nomatch'
差异解释
- 为什么3个问号而不是1个?
- 这个
?
字符已经是Where-Object
的别名。 -
??
在其他语言中用作空合并运算符,我想避免混淆。
- 这个
- 为什么我们需要命令之前的pipe道?
- 由于我正在利用stream水线来评估这个问题,我们仍然需要这个angular色来把这个条件转化为我们的function
- 如果我传入数组会发生什么?
- 我们得到每个值的结果; 即
-2..2 |??? 'match' : 'nomatch'
-2..2 |??? 'match' : 'nomatch'
match, match, nomatch, match, match
-2..2 |??? 'match' : 'nomatch'
给出:match, match, nomatch, match, match
(即因为任何非零整数评估为true
;而零评估为false
)。 - 如果你不想要的话,将数组转换为布尔值;
([bool](-2..2)) |??? 'match' : 'nomatch'
([bool](-2..2)) |??? 'match' : 'nomatch'
(或者简单地说:[bool](-2..2) |??? 'match' : 'nomatch'
)
- 我们得到每个值的结果; 即
IIf <condition> <condition-is-true> <condition-is-false>
请参阅: PowerShell内联如果(IIf)