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

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

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

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


当前回答

因为我已经用过很多次了,没有看到它列在这里,我将添加我的部分:

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

最丑的!

有点源

其他回答

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

为了在表达式中或作为表达式使用,而不仅仅是赋值,将它包装在$()中,这样:

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

我也在寻找一个更好的答案,虽然爱德华文章中的解决方案是“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" 

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

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的构造是:

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

Powershell 7有这个功能。

PS C:\Users\js> 0 ? 'yes' : 'no'
no
PS C:\Users\js> 1 ? 'yes' : 'no'
yes