PowerShell中的三元运算符

时间:2015-07-10 13:26:43

标签: powershell ternary-operator conditional-operator

据我所知,PowerShell似乎没有所谓的ternary operator的内置表达式。

例如,在支持三元运算符的C语言中,我可以编写如下内容:

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

如果在PowerShell中确实不存在,那么实现相同结果的最佳方法(即易于阅读和维护)是什么?

14 个答案:

答案 0 :(得分:228)

$result = If ($condition) {"true"} Else {"false"}

其他一切都是偶然的复杂性,因此应该避免。

用于或作为表达,而不仅仅是作业,将其包装在$()中,因此:

write-host  $(If ($condition) {"true"} Else {"false"}) 

答案 1 :(得分:43)

我能够提出的最接近的PowerShell构造是:

@({'condition is false'},{'condition is true'})[$condition]

答案 2 :(得分:24)

根据此PowerShell blog post,您可以创建别名来定义?:运算符:

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})

答案 3 :(得分:20)

我也是,寻找更好的答案,虽然爱德华的帖子中的解决方案是“好的”,但我想出了一个更自然的solution in this blog post

短而甜蜜:

# ---------------------------------------------------------------------------
# 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" 

答案 4 :(得分:14)

从PowerShell版本7开始,PowerShell内置了三元运算符。

1 -gt 2 ? "Yes" : "No"
# Returns "No"

1 -gt 2 ? 'Yes' : $null
# Get a $null response for false-y return value

答案 5 :(得分:9)

由于在分配值时通常使用三元运算符,因此它应返回一个值。这是可行的方式:

$var=@("value if false","value if true")[[byte](condition)]

愚蠢,但工作。此结构也可用于快速将int转换为另一个值,只需添加数组元素并指定一个返回基于0的非负值的表达式。

答案 6 :(得分:9)

尝试使用powershell的开关语句作为替代方案,尤其是对于变量赋值 - 多行,但可读。

实施例,

$WinVer = switch ( Test-Path $Env:windir\SysWOW64 ) {
  $true    { "64-bit" }
  $false   { "32-bit" }
}
"This version of Windows is $WinVer"

答案 7 :(得分:5)

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

答案 8 :(得分:4)

由于我已经多次使用过这个并没有在此处列出,我将添加我的文章:

$var = @{$true="this is true";$false="this is false"}[1 -eq 1]

最丑陋的!

kinda source

答案 9 :(得分:3)

PowerShell目前没有原生Inline If(或ternary If),但您可以考虑使用自定义cmdlet:

IIf <condition> <condition-is-true> <condition-is-false>
请参阅:PowerShell Inline If (IIf)

答案 10 :(得分:3)

我最近改进了(打开PullRequest)PoweShell lib'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)或scriptblock {$ b -eq 4}

如果变量表达式中的变量为$ null或不存在,则将替代表达式计算为输出。

答案 11 :(得分:1)

如果您只是在寻找一种基于布尔条件分配/返回字符串或数字的语法上简单的方法,则可以使用乘法运算符,如下所示:

"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”等不起作用。

答案 12 :(得分:1)

PowerShell 7.0 版中引入了 PowerShell 中的三元运算符。

[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

答案 13 :(得分:0)

这是另一种自定义函数方法:

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的别名。
    • ??在其他语言中用作空合并运算符,我想避免混淆。
  • 为什么我们在命令之前需要管道?
    • 由于我正在利用管道来评估这个问题,我们仍然需要这个字符来将条件传递给我们的函数
  • 如果我传入一个数组怎么办?
    • 我们得到每个值的结果;即-2..2 |??? 'match' : 'nomatch'给出:match, match, nomatch, match, match(即因为任何非零的int评估为true;而零评估为false)。
    • 如果您不想这样,请将数组转换为bool; ([bool](-2..2)) |??? 'match' : 'nomatch'(或简称:[bool](-2..2) |??? 'match' : 'nomatch'