PowerShell内联If(IIf)

mf98qq94  于 2023-05-17  发布在  Shell
关注(0)|答案(7)|浏览(143)

如何创建一个带有内联If(IIf)的a语句,另请参阅:Immediate ifternary If)中的任何一个?
如果你也认为这应该是一个原生的PowerShell函数,请投票支持:https://connect.microsoft.com/PowerShell/feedback/details/1497806/iif-statement-if-shorthand

更新(2019年10月7日)

Microsoft Connect已经退役了,但好消息是support for a ternary operator in PowerShell (Core) language似乎正在路上。

mkh04yzy

mkh04yzy1#

您可以使用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-09-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}

(Note Else部分通常需要在例如循环,需要重置$a。)
使用IIf cmdlet,它看起来像这样:

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

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

  • 添加2014-09-19:*

IIf cmdlet进行了微小更改,该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")}

请注意,如果相关注册表(HKCU:\Volatile Environment)不存在,则命令$VolatileEnvironment.GetValue("UserName")通常会导致**“You cannot call a method on a null-valued expression."**错误;命令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>表达式,并将结果转换为布尔值,以确定接下来应该计算哪个分支:
如果<condition>表达式为true,则执行<if-true>表达式如果<condition>表达式为false,则执行<if-false>表达式

示例

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

7y4bm7vi2#

**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
lbsnaicq

lbsnaicq3#

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

tp5buhyn4#

这里是另一种方法:

$condition = $false

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

dfuffjeb5#

来自博客文章 DIY: Ternary operator

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})

这是迄今为止我看到的最接近的变体。

busg9geu

busg9geu6#

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
vmdwslir

vmdwslir7#

PowerShell不支持内联ifs。你必须创建自己的函数(另一个答案建议),或者在一行中合并if/else语句(另一个答案也建议)。

相关问题