PowerShell Inline If (IIf)
Как создать оператор a со встроенным If (IIf, см. Также:http://en.wikipedia.org/wiki/IIf или троичная если) в PowerShell?
Если вы также считаете, что это должна быть собственная функция PowerShell, проголосуйте за это: https://connect.microsoft.com/PowerShell/feedback/details/1497806/iif-statement-if-shorthand
6 ответов
вы можете использовать собственный способ PowerShell:
"The condition is " + (&{If($Condition) {"True"} Else {"False"}}) + "."
но поскольку это добавляет много скобок и скобок к вашему синтаксису, вы можете рассмотреть следующий (возможно, один из самых маленьких существующих) командлет:
Function IIf($If, $Right, $Wrong) {If ($If) {$Right} Else {$Wrong}}
что упростит вашу команду до:
"The condition is " + (IIf $Condition "True" "False") + "."
добавлено 2014-09-19:
я использую IIf
командлет теперь на некоторое время, и я все еще думаю, что он сделает синтаксисы более читаемыми в много случаев, но поскольку я согласен с замечанием Джейсона о нежелательном побочном эффекте, что оба возможных значения будут оцениваться даже, очевидно, используется только одно значение, я изменил IIf
командлет немного:
Function IIf($If, $IfTrue, $IfFalse) {
If ($If) {If ($IfTrue -is "ScriptBlock") {&$IfTrue} Else {$IfTrue}}
Else {If ($IfFalse -is "ScriptBlock") {&$IfFalse} Else {$IfFalse}}
}
теперь может добавить блок скриптов (в окружении {}
's) вместо объекта, который не будет проверяться, если это не требуется, как показано в этом примере:
IIf $a {1/$a} NaN
или помещенный inline:
"The multiplicative inverse of $a is $(IIf $a {1/$a} NaN)."
в случае $a
имеет значение, отличное от нуля, возвращается мультипликативный обратный; в противном случае он вернет NaN
(где {1/$a}
не оценивается).
еще один хороший пример, где он сделает тихий неоднозначный синтаксис намного проще (особенно в случае, если вы хотите поместить его в строку), где вы хотите запустить метод на объекте, который потенциально может быть $Null
.
Туземец!--19-->’ способ сделать это, было бы что-то вроде этого:
If ($Object) {$a = $Object.Method()} Else {$a = $null}
(обратите внимание, что the Else
часть часто необходима в например петлях где вам будет нужно переустановить $a
.)
с IIf
командлет будет выглядеть так:
$a = IIf $Object {$Object.Method()}
(обратите внимание, что если $Object
is $Null
, $a
будет автоматически установлено в $Null
, если не $IfFalse
значение не задано.)
добавлено 2014-09-19:
незначительное изменение в IIf
командлет, который теперь задает текущий объект ($_
или $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]
type), то IIf
командлет не отменяет текущий объект, например:
$RegistryKeys | ForEach {
$UserName = IIf ($Number -lt 5) {$_.GetValue("UserName")}
}
или:
$RegistryKeys | ForEach {
$UserName = IIf [Bool]$VolatileEnvironment {$_.OtherMethod()}
}
на самом деле Powershell возвращает значения, которые не были назначены
$a = if ($condition) { $true } else { $false }
пример:
"The item is $(if ($price -gt 100) { 'expensive' } else { 'cheap' })"
давайте попробуем это:
$price = 150
The item is expensive
$price = 75
The item is cheap
вот еще один способ:
$condition = $false
"The condition is $(@{$true = "true"; $false = "false"}[$condition])"
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 не поддерживает встроенные ifs. Вам придется создать свою собственную функцию (как предлагает другой ответ) или объединить операторы if/else в одной строке (как также предлагает другой ответ).