如何在PowerShell中创建包含内联If(IIf,也称为:即时If或三元If)的语句?
如果您认为这应该是PowerShell的本机函数,请为此投票: https://connect.microsoft.com/PowerShell/feedback/details/1497806/iif-statement-if-shorthand
如何在PowerShell中创建包含内联If(IIf,也称为:即时If或三元If)的语句?
如果您认为这应该是PowerShell的本机函数,请为此投票: https://connect.microsoft.com/PowerShell/feedback/details/1497806/iif-statement-if-shorthand
你可以使用PowerShell的本地方法:
"The condition is " + (&{If($Condition) {"True"} Else {"False"}}) + "."
但是,由于这会给您的语法添加很多括号和方括号,因此您可以考虑使用以下CmdLet(可能是现有CmdLet中最小的之一):
Function IIf($If, $Right, $Wrong) {If ($If) {$Right} Else {$Wrong}}
"The condition is " + (IIf $Condition "True" "False") + "."
添加于2014年9月19日:
我已经使用IIf
命令一段时间了,我仍然认为在许多情况下它可以使语法更易读,但是我同意Jason提到的一个不想要的副作用,即明显只使用一个值时,两个可能的值都将被评估。因此,我对IIf
命令进行了一些修改:
Function IIf($If, $IfTrue, $IfFalse) {
If ($If) {If ($IfTrue -is "ScriptBlock") {&$IfTrue} Else {$IfTrue}}
Else {If ($IfFalse -is "ScriptBlock") {&$IfFalse} Else {$IfFalse}}
}
{}
包围)而不是对象,如果不需要该对象,则不会对其进行评估,如下面的示例所示: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}
$a
的循环等情况中,Else
部分经常是必需的。)IIf
命令时,它将如下所示:)$a = IIf $Object {$Object.Method()}
$Object
为$Null
,并且没有提供$IfFalse
值,则$a
将自动设置为$Null
。)
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")}
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
命令不会改变当前对象,例如:$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>
表达式为真,则执行<if-true>
表达式。 如果<condition>
表达式为假,则执行<if-false>
表达式。
示例:
"The multiplicative inverse of $a is $($a ? (& {1/$a}) : 'NaN')."
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
'The condition is {0}.' -f ('false','true')[$condition]
$condition = $false
"The condition is $(@{$true = "true"; $false = "false"}[$condition])"
$Condition = "Has Text"
和 $Condition = 10
这样的情况下返回空值(有时可能是期望的,但不符合 PowerShell 的风格),因此我会将其更改为:"条件为 $(@("False", "True")[[Bool]$Condition])"
。 - iRon来自博客文章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})
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
PowerShell不支持内联if语句。您需要创建自己的函数(如另一个答案所建议的),或将if / else语句组合在单行上(如另一个答案也建议的)。