2014-09-05 18 views

risposta

48

È possibile utilizzare maniera nativa del PowerShell:

"The condition is " + (&{If($Condition) {"True"} Else {"False"}}) + "." 

Ma questo aggiunge un sacco di parentesi e le staffe per la sintassi, si potrebbe prendere in considerazione il seguito (probabilmente uno dei più piccoli esistenti) cmdlet:

Function IIf($If, $Right, $Wrong) {If ($If) {$Right} Else {$Wrong}} 

che semplificherà la vostra comando per:

"The condition is " + (IIf $Condition "True" "False") + "." 

Aggiunto 2014/09/19:

Sono stato utilizzando il cmdlet IIf adesso per un po 'e io continuo a pensare che renderà sintassi più leggibile in un sacco di casi, ma siccome concordo con la nota di Jason sull'effetto collaterale indesiderato che verranno valutati entrambi i valori possibili, ovviamente è utilizzato solo un valore, ho modificato un po 'il cmdlet IIf:

Function IIf($If, $IfTrue, $IfFalse) { 
    If ($If) {If ($IfTrue -is "ScriptBlock") {&$IfTrue} Else {$IfTrue}} 
    Else {If ($IfFalse -is "ScriptBlock") {&$IfFalse} Else {$IfFalse}} 
} 

Ora è potrebbe aggiungere uno ScriptBlock (circondato da {} 's), invece di un oggetto che non sarà valutato se non è necessario, come mostrato in questo esempio:

IIf $a {1/$a} NaN 

o posto in linea:

"The multiplicative inverse of $a is $(IIf $a {1/$a} NaN)." 

Nel caso $a ha un valore diverso da zero, viene restituito l'inverso moltiplicativo; in caso contrario, restituirà NaN (in cui lo {1/$a} non viene valutato).

Un altro bel esempio in cui si farà una tranquilla sintassi ambigua molto più semplice (in particolare nel caso in cui si desidera posizionarlo in linea) è dove si desidera eseguire un metodo su un oggetto che potrebbe essere potenzialmente $Null. Il 'If' modo nativo per fare questo, sarebbe qualcosa di simile:

If ($Object) {$a = $Object.Method()} Else {$a = $null} 

(. Si noti che la parte Else spesso è richiesto, ad esempio in loop dove sarà necessario reimpostare $a)

Con il IIf cmdlet che sarà simile a questa:

$a = IIf $Object {$Object.Method()} 

(Notare che se il $Object è $Null, $a sarà automatica Si può impostare su se non viene fornito il valore $IfFalse.)


Aggiunto 2014/09/19:

Modifica minore al IIf cmdlet che ora definisce l'oggetto corrente ($_ o $PSItem):

Function IIf($If, $IfTrue, $IfFalse) { 
    If ($If -IsNot "Boolean") {$_ = $If} 
    If ($If) {If ($IfTrue -is "ScriptBlock") {&$IfTrue} Else {$IfTrue}} 
    Else {If ($IfFalse -is "ScriptBlock") {&$IfFalse} Else {$IfFalse}} 
} 

Questo significa che si può semplificare una dichiarazione (il modo in PowerShell) con un metodo su un oggetto che potrebbe potenzialmente essere $Null.

La sintassi generale per questo sarà ora $a = IIf $Object {$_.Method()}. Un esempio più comune avrà un aspetto simile:

$VolatileEnvironment = Get-Item -ErrorAction SilentlyContinue "HKCU:\Volatile Environment" 
$UserName = IIf $VolatileEnvironment {$_.GetValue("UserName")} 

Nota che il comando $VolatileEnvironment.GetValue("UserName") sarà di norma un "Non si può chiamare un metodo su un'espressione null-valore." Errore se il registro interessato (HKCU:\Volatile Environment) non esiste; dove il comando IIf $VolatileEnvironment {$_.GetValue("UserName")} restituirà solo $Null.

Se il parametro $If è una condizione (qualcosa come $Number -lt 5) o costretti a una condizione (con il tipo [Bool]), il cmdlet IIf non prevalere l'oggetto corrente, ad esempio:

$RegistryKeys | ForEach { 
    $UserName = IIf ($Number -lt 5) {$_.GetValue("UserName")} 
} 

Oppure:

$RegistryKeys | ForEach { 
    $UserName = IIf [Bool]$VolatileEnvironment {$_.OtherMethod()} 
} 
+3

Il tuo primo esempio può essere un po 'più semplice: "La condizione è $ (Se ($ Condizione) {" Vero "} Altro { "False"})." –

+2

Il secondo esempio è bello se i valori non hanno effetti collaterali, ma non va bene se ci sono effetti collaterali perché gli effetti collaterali si verificano sia su $ Right che su $ Wrong prima di entrare nella funzione IIf. –

3

Ecco un altro modo:

$condition = $false 

"The condition is $(@{$true = "true"; $false = "false"}[$condition])" 
+0

Bello, ma non valuta la condizione e quindi non restituisce nulla in casi come '$ Condition =" Ha testo "' e '$ Condition = 10' (che a volte potrebbe essere desiderato, ma non come PowerShell), quindi cambierei a: '" La condizione è $ (@ ("False", "True") [[Bool] $ Condizione]) "' – iRon

+0

Hai ragione, per questo specifico esempio. Se $ condition = 10, lo farebbe in questo modo: "La condizione è $ (@ {$ true =" maggiore di 50 "; $ false =" meno di 50 "} [$ condition -gt 50])" – ojk

18
'The condition is {0}.' -f ('false','true')[$condition] 
+0

mjolinor .Uso intelligente dell'operatore indice lì (in combinazione con la formattazione composita). –

-3

PowerShell non supporta i inline ifs. Dovrai creare la tua funzione (come suggerisce un'altra risposta), o combinare if/else statement su una singola riga (come suggerisce anche un'altra risposta).

9

realtà PowerShell dà di nuovo i valori che non sono stati assegnati

$a = if ($condition) { $true } else { $false } 

Esempio:

"The item is $(if ($price -gt 100) { 'expensive' } else { 'cheap' })" 

Proviamo fuori:

$price = 150 
The item is expensive 
$price = 75 
The item is cheap 
0
Function Compare-InlineIf 
{ 
[CmdletBinding()] 
    Param( 
     [Parameter( 
      position=0, 
      Mandatory=$false, 
      ValueFromPipeline=$false 
     )] 
     $Condition, 
     [Parameter( 
      position=1, 
      Mandatory=$false, 
      ValueFromPipeline=$false 
     )] 
     $IfTrue, 
     [Parameter( 
      position=2, 
      Mandatory=$false, 
      ValueFromPipeline=$false 
     )] 
     $IfFalse 
    ) 
    Begin{ 
     Function Usage 
     { 
      write-host @" 
Syntax 
    Compare-InlineIF [[-Condition] <test>] [[-IfTrue] <String> or <ScriptBlock>] 
[[-IfFalse] <String> or <ScriptBlock>] 
Inputs 
    None 
    You cannot pipe objects to this cmdlet. 

Outputs 
    Depending on the evaluation of the condition statement, will be either the IfTrue or IfFalse suplied parameter values 
Examples 
    .Example 1: perform Compare-InlineIf : 
    PS C:\>Compare-InlineIf -Condition (6 -gt 5) -IfTrue "yes" -IfFalse "no" 

    yes 

    .Example 2: perform IIF : 
    PS C:\>IIF (6 -gt 5) "yes" "no" 

    yes 

    .Example 3: perform IIF : 
    PS C:\>IIF `$object "`$true","`$false" 

    False 

    .Example 4: perform IIF : 
    `$object = Get-Item -ErrorAction SilentlyContinue "HKCU:\AppEvents\EventLabels\.Default\" 
    IIf `$object {`$_.GetValue("DispFilename")} 

    @mmres.dll,-5824 
"@ 
     } 
    } 
    Process{ 
     IF($IfTrue.count -eq 2 -and -not($IfFalse)){ 
      $IfFalse = $IfTrue[1] 
      $IfTrue = $IfTrue[0] 
     }elseif($iftrue.count -ge 3 -and -not($IfFalse)){ 
      Usage 
      break 
     } 
     If ($Condition -IsNot "Boolean") 
     { 
      $_ = $Condition 
     } else {} 
     If ($Condition) 
     { 
      If ($IfTrue -is "ScriptBlock") 
      { 
       &$IfTrue 
      } 
      Else 
      { 
       $IfTrue 
      } 
     } 
     Else 
     { 
      If ($IfFalse -is "ScriptBlock") 
      { 
       &$IfFalse 
      } 
      Else 
      { 
       $IfFalse 
      } 
     } 
    } 
    End{} 
} 
Set-Alias -Name IIF -Value Compare-InlineIf 
+0

Questo è solo un repost/lieve miglioramento della funzione personalizzata che è stata discussa sopra. Nulla di veramente nuovo se non il piccolo pezzo che determina se due elementi sono stati passati per il secondo parametro e nulla per il terzo, lo divide in entrambi i parametri. Ciò lo rende in grado di agire in modo coerente con VBA in cui l'IIF è comune. – HeyNow