据我所知,PowerShell似乎没有用于所谓三元运算符的内置表达式。
例如,在支持三元操作符的C语言中,我可以这样写:
<condition> ? <condition-is-true> : <condition-is-false>;
如果PowerShell中没有这样的功能,那么要达到同样的效果(即易于阅读和维护),最好的方法是什么?
据我所知,PowerShell似乎没有用于所谓三元运算符的内置表达式。
例如,在支持三元操作符的C语言中,我可以这样写:
<condition> ? <condition-is-true> : <condition-is-false>;
如果PowerShell中没有这样的功能,那么要达到同样的效果(即易于阅读和维护),最好的方法是什么?
我能够想出的最接近PowerShell的构造是:
@({'condition is false'},{'condition is true'})[$condition]
由于三元操作符通常在赋值时使用,因此它应该返回一个值。这是可行的方法:
$var=@("value if false","value if true")[[byte](condition)]
愚蠢,但有效。此外,这种结构可以用于快速将int转换为另一个值,只需添加数组元素并指定一个返回基于0的非负值的表达式。
因为我已经用过很多次了,没有看到它列在这里,我将添加我的部分:
$var = @{$true="this is true";$false="this is false"}[1 -eq 1]
最丑的!
有点源
根据这篇PowerShell博客文章,你可以创建一个别名来定义?:operator:
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})
我也在寻找一个更好的答案,虽然爱德华文章中的解决方案是“ok”,但我在这篇博客文章中提出了一个更自然的解决方案
简短而甜蜜:
# ---------------------------------------------------------------------------
# Name: Invoke-Assignment
# Alias: =
# Author: Garrett Serack (@FearTheCowboy)
# Desc: Enables expressions like the C# operators:
# Ternary:
# <condition> ? <trueresult> : <falseresult>
# e.g.
# status = (age > 50) ? "old" : "young";
# Null-Coalescing
# <value> ?? <value-if-value-is-null>
# e.g.
# 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"
$result = If ($condition) {"true"} Else {"false"}
为了在表达式中或作为表达式使用,而不仅仅是赋值,将它包装在$()中,这样:
write-host $(If ($condition) {"true"} Else {"false"})
下面是另一种自定义函数方法:
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'
差异的解释
Why is it 3 question marks instead of 1? The ? character is already an alias for Where-Object. ?? is used in other languages as a null coalescing operator, and I wanted to avoid confusion. Why do we need the pipe before the command? Since I'm utilising the pipeline to evaluate this, we still need this character to pipe the condition into our function What happens if I pass in an array? We get a result for each value; i.e. -2..2 |??? 'match' : 'nomatch' gives: match, match, nomatch, match, match (i.e. since any non-zero int evaluates to true; whilst zero evaluates to false). If you don't want that, convert the array to a bool; ([bool](-2..2)) |??? 'match' : 'nomatch' (or simply: [bool](-2..2) |??? 'match' : 'nomatch')
PowerShell目前没有一个本地内联If(或三元If),但你可以考虑使用自定义cmdlet:
IIf <condition> <condition-is-true> <condition-is-false>
参见:PowerShell内联If (IIf)
尝试powershell的switch语句作为替代,特别是对于变量赋值-多行,但可读。
的例子,
$WinVer = switch ( Test-Path -Path "$Env:windir\SysWOW64" ) {
$true { "64-bit" }
$false { "32-bit" }
}
"This version of Windows is $WinVer"
我最近改进了(打开PullRequest) PoweShell库'Pscx'中的三元条件和空合并操作符 请看我的解决办法。
我的github主题分支:UtilityModule_Invoke-Operators
功能:
Invoke-Ternary
Invoke-TernaryAsPipe
Invoke-NullCoalescing
NullCoalescingAsPipe
别名
Set-Alias :?: Pscx\Invoke-Ternary -Description "PSCX alias"
Set-Alias ?: Pscx\Invoke-TernaryAsPipe -Description "PSCX alias"
Set-Alias :?? Pscx\Invoke-NullCoalescing -Description "PSCX alias"
Set-Alias ?? Pscx\Invoke-NullCoalescingAsPipe -Description "PSCX alias"
使用
<condition_expression> |?: <true_expression> <false_expression>
<variable_expression> |?? <alternate_expression>
作为表达式,你可以传递: $null,一个文字,一个变量,一个“外部”表达式($b -eq 4)或一个脚本块{$b -eq 4} 如果变量表达式中的变量为$null或不存在,则计算备用表达式作为输出。
Powershell 7有这个功能。
PS C:\Users\js> 0 ? 'yes' : 'no'
no
PS C:\Users\js> 1 ? 'yes' : 'no'
yes
如果你只是在寻找一种语法上简单的方法来基于布尔条件赋值/返回一个字符串或数字,你可以使用这样的乘法运算符:
"Condition is "+("true"*$condition)+("false"*!$condition)
(12.34*$condition)+(56.78*!$condition)
如果你只对正确的结果感兴趣,你可以完全忽略错误的部分(反之亦然),例如一个简单的评分系统:
$isTall = $true
$isDark = $false
$isHandsome = $true
$score = (2*$isTall)+(4*$isDark)+(10*$isHandsome)
"Score = $score"
# or
# "Score = $((2*$isTall)+(4*$isDark)+(10*$isHandsome))"
注意,布尔值不应该是乘法运算中的前项,即$condition*"true"等将不起作用。
从PowerShell版本7开始,三元运算符被内置到PowerShell中。
1 -gt 2 ? "Yes" : "No"
# Returns "No"
1 -gt 2 ? 'Yes' : $null
# Get a $null response for false-y return value
PowerShell中的三元运算符是在PowerShell version7.0中引入的。
[Condition] ? (output if True) : (output if False)
例01
$a = 5; $b = 6
($a -gt $b) ? "True" : "False"
输出
False
例子02
($a -gt $b) ? ("$a is greater than $b") : ("$a is less than $b")
输出
5 is less than 6
更多的信息 https://www.tutorialspoint.com/how-ternary-operator-in-powershell-works