PowerShell中的三元运算符

据我所知,PowerShell似乎没有所谓的三元运算符的内置表达式。

例如,在支持三元操作符的C语言中,我可以这样写:

<condition> ? <condition-is-true> : <condition-is-false>;

如果PowerShell中没有这样的功能,那么要达到同样的效果(即易于阅读和维护),最好的方法是什么?

202390 次浏览

我能够想出的最接近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]

最丑的!

kinda source

根据这个PowerShell博客文章,你可以创建一个别名来定义?:操作符:

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'

差异的解释

  • 为什么是三个问号而不是一个?
    • ?字符已经是Where-Object的别名。
    • ??在其他语言中用作空合并运算符,我想避免混淆。
    • 李< / ul > < / >
    • 为什么我们在命令之前需要管道?
      • 由于我使用管道来计算这个,我们仍然需要这个字符将条件管道到我们的函数中
      • 李< / ul > < / >
      • 如果传入一个数组会发生什么?
        • 我们得到每个值的结果;例如,-2..2 |??? 'match' : 'nomatch'给出:match, match, nomatch, match, match(即,由于任何非零int计算为true;而0的计算结果为false)。
        • 如果你不想这样,将数组转换为bool类型;([bool](-2..2)) |??? 'match' : 'nomatch'(或简单地:[bool](-2..2) |??? 'match' : 'nomatch')
        • 李< / ul > < / >

PowerShell 目前不 <强> < / >强不有一个原生的内联如果(或三元如果),但你可以考虑使用自定义cmdlet:

IIf <condition> <condition-is-true> <condition-is-false>

看:PowerShell内联If (IIf)

尝试powershell的开关语句作为替代,特别是对于变量赋值-多行,但可读。

的例子,

$WinVer = switch ( Test-Path "$Env:windir\SysWOW64" ) {
$true    { "64-bit" }
$false   { "32-bit" }
}
"This version of Windows is $WinVer"
我最近改进了(打开PullRequest) PoweShell库'Pscx'
中的三元条件和空合并操作符 请看我的解决办法。

< p > < br > 我的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有这个功能。https://toastit.dev/2019/09/25/ternary-operator-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
< p >更多的信息 https://www.tutorialspoint.com/how-ternary-operator-in-powershell-works < / p >