Operador ternário em PowerShell

Pelo que sei, PowerShell não parece ter uma expressão incorporada para o chamado operador ternário {[[3]}.

por exemplo, na linguagem C, que suporta o operador ternário, eu poderia escrever algo como:

<condition> ? <condition-is-true> : <condition-is-false>;
Se isso não existe realmente em PowerShell, qual seria a melhor maneira (ou seja, fácil de ler e manter) de alcançar o mesmo resultado?

Author: andiDo, 2015-07-10

10 answers

$result = If ($condition) {"true"} Else {"false"}
Tudo o resto é complexidade incidental e, portanto, deve ser evitado.

Para utilização em ou como expressão, não apenas uma atribuição, embrulhe-a em $(), assim:

write-host  $(If ($condition) {"true"} Else {"false"}) 
 181
Author: fbehrens, 2017-04-06 11:33:12

A construção de Powershell mais próxima que consegui arranjar para imitar é:

. ({'condition is false'},{'condition is true'})[$condition]
 30
Author: mjolinor, 2015-07-10 13:52:07

De acordo com este PowerShell blog post , pode criar um nome alternativo para definir um ?: operador:

set-alias ?: Invoke-Ternary -Option AllScope -Description "PSCX filter alias"
filter Invoke-Ternary ([scriptblock]$decider, [scriptblock]$ifTrue, [scriptblock]$ifFalse) 
{
   if (&$decider) { 
      &$ifTrue
   } else { 
      &$ifFalse 
   }
}

Usa-o assim:

$total = ($quantity * $price ) * (?:  {$quantity -le 10} {.9} {.75})
 21
Author: Edward Brey, 2015-11-12 13:01:29

Eu também, procurei uma resposta melhor, e enquanto a solução no post de Edward é "ok", eu cheguei com uma solução muito mais natural {[[4]}Neste post no blog

Curto e doce:

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

O que torna mais fácil fazer coisas como (mais exemplos no post do blog):

$message == ($age > 50) ? "Old Man" :"Young Dude" 
 17
Author: Garrett Serack, 2015-12-11 19:21:10

Uma vez que um operador ternário é normalmente usado ao atribuir valor, ele deve retornar um valor. Esta é a maneira que pode funcionar:

$var=@("value if false","value if true")[[byte](condition)]
Estúpido, mas a trabalhar. Também esta construção pode ser usada para transformar rapidamente um int em outro valor, basta adicionar elementos de array e especificar uma expressão que retorna valores não-negativos baseados em 0.
 10
Author: Vesper, 2015-07-10 14:16:36
Uma vez que já usei isto muitas vezes e não o vi listado aqui, vou adicionar a minha peça:

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

O mais feio de todos !

Tipo de origem

 5
Author: sodawillow, 2015-09-16 18:44:22

Tente a declaração de powershell como uma alternativa, especialmente para a atribuição de variáveis - múltiplas linhas, mas legível.

Exemplo,

$WinVer = switch ( Test-Path $Env:windir\SysWOW64 ) {
  $true    { "64-bit" }
  $false   { "32-bit" }
}
"This version of Windows is $WinVer"
 3
Author: nudl, 2018-01-24 20:00:37

O PowerShell não tem actualmente um nativo Se (ou ternário se ) mas pode considerar a utilização do cmdlet personalizado:

IIf <condition> <condition-is-true> <condition-is-false>
Ver: PowerShell Inline If (IIf)
 1
Author: iRon, 2018-01-16 08:00:54

Melhorei recentemente (Open PullRequest) os operadores ternários condicionais e nulos de coalescing na PoweShell lib 'Pscx'
O Pls procura a minha solução.


o meu ramo temático github: UtilityModule_Invoke-Operators

Funções:

Invoke-Ternary
Invoke-TernaryAsPipe
Invoke-NullCoalescing
NullCoalescingAsPipe

Outros nomes

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"

Utilização

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

<variable_expression> |?? <alternate_expression>

Como expressão pode passar:
$null, um literal, uma variável, uma expressão ' externa '($b-eq 4) ou um scriptblock {$b-eq 4}

Se uma variável na expressão da variável é $null ou não existente, a expressão alternativa é avaliada como saída.

 1
Author: andiDo, 2018-06-11 15:42:56

Aqui está uma abordagem alternativa de função personalizada:

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'

Exemplo

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

Diferenças Explicadas

    Por que são 3 pontos de interrogação em vez de 1?
    • o carácter ? já é um pseudónimo de Where-Object.
    • ?? é usado em outras línguas como um operador de coalescing nulo, e eu queria evitar confusão.
    Porque precisamos do tubo antes do comando?
    • já que estou a utilizar o pipeline para avaliar isso, ainda precisamos deste personagem para canalizar a condição para a nossa função
    O que acontece se eu passar numa matriz?
    • obtemos um resultado para cada valor; isto é -2..2 |??? 'match' : 'nomatch' dá: match, match, nomatch, match, match (isto é, uma vez que qualquer int não-zero avalia para true; enquanto que o zero avalia para false).
    • Se você não quiser isso, converta o array para um bool; ([bool](-2..2)) |??? 'match' : 'nomatch' (ou simplesmente: [bool](-2..2) |??? 'match' : 'nomatch')
 0
Author: JohnLBevan, 2017-06-13 16:58:22