Ternary operator in PowerShell

后端 未结 13 2016
忘掉有多难
忘掉有多难 2020-11-28 03:56

From what I know, PowerShell doesn\'t seem to have a built-in expression for the so-called ternary operator.

For example, in the C language, which supports the terna

相关标签:
13条回答
  • 2020-11-28 04:18

    Here's an alternative custom function approach:

    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

    • 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')
    0 讨论(0)
  • 2020-11-28 04:20

    Per this PowerShell blog post, you can create an alias to define a ?: 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 
       }
    }
    

    Use it like this:

    $total = ($quantity * $price ) * (?:  {$quantity -le 10} {.9} {.75})
    
    0 讨论(0)
  • 2020-11-28 04:22

    If you're just looking for a syntactically simple way to assign/return a string or numeric based on a boolean condition, you can use the multiplication operator like this:

    "Condition is "+("true"*$condition)+("false"*!$condition)
    (12.34*$condition)+(56.78*!$condition)
    

    If you're only ever interested in the result when something is true, you can just omit the false part entirely (or vice versa), e.g. a simple scoring system:

    $isTall = $true
    $isDark = $false
    $isHandsome = $true
    
    $score = (2*$isTall)+(4*$isDark)+(10*$isHandsome)
    "Score = $score"
    # or
    # "Score = $((2*$isTall)+(4*$isDark)+(10*$isHandsome))"
    

    Note that the boolean value should not be the leading term in the multiplication, i.e. $condition*"true" etc. won't work.

    0 讨论(0)
  • 2020-11-28 04:23

    I've recently improved (open PullRequest) the ternary conditional and null-coalescing operators in the PoweShell lib 'Pscx'
    Pls have a look for my solution.


    My github topic branch: UtilityModule_Invoke-Operators

    Functions:

    Invoke-Ternary
    Invoke-TernaryAsPipe
    Invoke-NullCoalescing
    NullCoalescingAsPipe
    

    Aliases

    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"
    

    Usage

    <condition_expression> |?: <true_expression> <false_expression>
    
    <variable_expression> |?? <alternate_expression>
    

    As expression you can pass:
    $null, a literal, a variable, an 'external' expression ($b -eq 4) or a scriptblock {$b -eq 4}

    If a variable in the variable expression is $null or not existing, the alternate expression is evaluated as output.

    0 讨论(0)
  • 2020-11-28 04:26

    Powershell 7 has it. 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
    
    0 讨论(0)
  • 2020-11-28 04:27

    I too, looked for a better answer, and while the solution in Edward's post is "ok", I came up with a far more natural solution in this blog post

    Short and sweet:

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

    Which makes it easy to do stuff like (more examples in blog post):

    $message == ($age > 50) ? "Old Man" :"Young Dude" 
    
    0 讨论(0)
提交回复
热议问题