PowerShell 内联 If (IIf)

问题描述 投票:0回答:7

如何在 PowerShell 中创建内联

If
(IIf,另请参阅:立即 if三元 If)?

powershell iif
7个回答
125
投票

您可以使用PowerShell的本机方式:

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

但是,由于这会在语法中添加大量括号和方括号,因此您可能会考虑以下(可能是现有的最小的之一)CmdLet:

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

这将简化您的命令:

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

添加于2014年9月19日:

我现在已经使用

IIf
cmdlet 一段时间了,我仍然认为它在很多情况下会使语法更具可读性,但正如我同意 Jason 的注释,关于两个可能的值都将被评估的不需要的副作用即使显然只使用了一个值,我也稍微更改了
IIf
cmdlet:

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

现在您可能添加一个 ScriptBlock(由

{}
包围)而不是一个对象,如果不需要,则不会对其进行评估,如本示例所示:

IIf $a {1/$a} NaN

或内联放置:

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

如果

$a
的值不为零,则返回乘法逆元;否则,它将返回
NaN
(其中
{1/$a}
不被评估)。

另一个很好的例子,它将使安静的模糊语法变得更加简单(特别是当你想将其内联放置时)是你想要在一个可能是

$Null
的对象上运行一个方法。

执行此操作的原生“

If
”方式如下所示:

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

(请注意,

Else
部分通常需要在例如需要重置
$a
的循环中。)

使用

IIf
cmdlet,它将如下所示:

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

(请注意,如果

$Object
$Null
,如果未提供
$a
值,
$Null
将自动设置为
$IfFalse
。)


添加于2014年9月19日:

IIf
cmdlet 进行了细微更改,现在设置当前对象(
$_
$PSItem
):

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

这意味着您可以使用对象上的方法来简化语句(PowerShell 方式),该方法可能是

$Null

现在的通用语法是

$a = IIf $Object {$_.Method()}
。一个更常见的例子如下:

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

请注意,如果相关注册表 (

$VolatileEnvironment.GetValue("UserName")
) 不存在,则命令 HKCU:\Volatile Environment 通常会导致
“您无法在空值表达式上调用方法。”
错误;其中命令
IIf $VolatileEnvironment {$_.GetValue("UserName")}
将仅返回
$Null

如果

$If
参数是一个条件(类似于
$Number -lt 5
)或强制为一个条件(具有
[Bool]
类型),则
IIf
cmdlet 不会否决当前对象,例如:

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

或者:

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

添加于2020-03-20:

使用三元运算符语法

PowerShell 7.0 引入了使用三元运算符的新语法。它遵循 C# 三元运算符语法:

三元运算符的行为类似于简化的

if-else
语句。 计算
<condition>
表达式并转换结果 到一个布尔值来确定接下来应该评估哪个分支:

如果

<if-true>
表达式为 true,则执行
<condition>
表达式 如果
<if-false>
表达式为 false,则执行
<condition>
表达式

示例

"The multiplicative inverse of $a is $($a ? (& {1/$a}) : 'NaN')."

69
投票

Powershell 7+允许三元运算符:

$price = 150
$text = $price -gt 100 ? 'expensive' : 'cheap'
$text
# output: 
# expensive

Powershell 6(或更早版本)返回尚未分配的值。

$price = 150
$text = if ($price -gt 100) { 'expensive' } else { 'cheap' }
$text
# output:
# expensive

37
投票
'The condition is {0}.' -f ('false','true')[$condition]

5
投票

还有另一种方法:

$condition = $false

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

3
投票

来自博客文章DIY:三元运算符

Relevant code:
# —————————————————————————
# Name:   Invoke-Ternary
# Alias:  ?:
# Author: Karl Prosser
# Desc:   Similar to the C# ? : operator e.g. 
#            _name = (value != null) ? String.Empty : value;
# Usage:  1..10 | ?: {$_ -gt 5} {“Greater than 5;$_} {“Not greater than 5”;$_}
# —————————————————————————
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})

这是迄今为止我见过的最接近的变体。


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  

-1
投票

PowerShell 不支持内联 if。您必须创建自己的函数(正如另一个答案所建议的那样),或者将 if/else 语句组合在一行上(正如另一个答案所建议的那样)。

© www.soinside.com 2019 - 2024. All rights reserved.