首页 文章

PowerShell中的三元运算符

提问于
浏览
140

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

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

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

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

10 回答

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

    其他一切都是偶然的复杂性,因此要避免 .

    要在或作为表达式使用,而不仅仅是赋值,请将其包装在 $() 中,因此:

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

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

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

    根据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})
    
  • 20

    我也是,寻找更好的答案,而爱德华的帖子中的解决方案是"ok",我想出了一个更自然的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"
    
  • 0

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

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

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

  • 4

    尝试使用powershell的 switch 语句替代,特别是对于变量赋值 - 多行,但可读 .

    例,

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

    由于我已经多次使用这个并且没有在这里看到它,我将添加我的作品:

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

    最丑陋的!

    kinda source

  • 7

    我've recently improved (open PullRequest) the ternary conditional and null-coalescing operators in the PoweShell lib ' Pscx'
    请看看我的解决方案 .

    My github topic branch: 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,文字,变量,'external'表达式($ b -eq 4)或scriptblock {$ b -eq 4}

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

  • 39

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

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

    见:PowerShell Inline If (IIf)

  • 3

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

    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'
    

    Example

    1 -eq 1 |??? 'match' : 'nomatch'
    1 -eq 2 |??? 'match' : 'nomatch'
    

    Differences Explained

    • 为什么它是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'

相关问题