私が知っていることから、PowerShellはいわゆる 三項演算子 のための組み込み式を持っていないようです。
たとえば、三項演算子をサポートするC言語では、次のように書くことができます。
<condition> ? <condition-is-true> : <condition-is-false>;
それがPowerShellに実際には存在しない場合、同じ結果を達成するための最善の方法(つまり、読みやすく保守しやすい)は何でしょうか。
$result = If ($condition) {"true"} Else {"false"}
他のすべては付随的な複雑さであり、したがって避けるべきです。
代入だけではなく式で、または式として使用するには、$()
で囲みます。
write-Host $(If ($condition) {"true"} Else {"false"})
これをエミュレートするために私が思いつくことができた最も近いPowerShellの構成は、次のとおりです。
@({'condition is false'},{'condition is true'})[$condition]
これにより PowerShellブログ投稿 、?:
演算子を定義するためのエイリアスを作成することができます。
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})
私も、より良い答えを探しました。そして、Edwardの投稿の解決策は "ok"ですが、私ははるかに自然な解決策を思いつきました このブログ投稿の解決策
短くて甘い:
# ---------------------------------------------------------------------------
# Name: Invoke-Assignment
# Alias: =
# Author: Garrett Serack (@FearTheCowboy)
# Desc: Enables expressions like the C# operators:
# Ternary:
# <condition> ? <trueresult> : <falseresult>
# e.g.
# status = (age > 50) ? "old" : "young";
# Null-Coalescing
# <value> ?? <value-if-value-is-null>
# e.g.
# name = GetName() ?? "No Name";
#
# Ternary Usage:
# $status == ($age > 50) ? "old" : "young"
#
# Null Coalescing Usage:
# $name = (get-name) ? "No Name"
# ---------------------------------------------------------------------------
# returns the evaluated value of the parameter passed in,
# executing it, if it is a scriptblock
function eval($item) {
if( $item -ne $null ) {
if( $item -is "ScriptBlock" ) {
return & $item
}
return $item
}
return $null
}
# an extended assignment function; implements logic for Ternarys and Null-Coalescing expressions
function Invoke-Assignment {
if( $args ) {
# ternary
if ($p = [array]::IndexOf($args,'?' )+1) {
if (eval($args[0])) {
return eval($args[$p])
}
return eval($args[([array]::IndexOf($args,':',$p))+1])
}
# null-coalescing
if ($p = ([array]::IndexOf($args,'??',$p)+1)) {
if ($result = eval($args[0])) {
return $result
}
return eval($args[$p])
}
# neither ternary or null-coalescing, just a value
return eval($args[0])
}
return $null
}
# alias the function to the equals sign (which doesn't impede the normal use of = )
set-alias = Invoke-Assignment -Option AllScope -Description "FearTheCowboy's Invoke-Assignment."
これにより、次のようなことを簡単に行うことができます(ブログ投稿の他の例)。
$message == ($age > 50) ? "Old Man" :"Young Dude"
PowerShellのswitchステートメントを代替変数として試してみてください。特に変数の代入のために。
例、
$WinVer = switch ( Test-Path $Env:windir\SysWOW64 ) {
$true { "64-bit" }
$false { "32-bit" }
}
"This version of Windows is $WinVer"
通常、値を割り当てるときには3項演算子が使用されるため、値を返す必要があります。これはうまくいく方法です:
$var=@("value if false","value if true")[[byte](condition)]
愚かな、しかし働いている。また、この構造は、intを別の値に素早く変換し、配列要素を追加し、0から始まる負以外の値を返す式を指定するためにも使用できます。
私はすでにこれを何度も使っていて、ここにリストされているのを見なかったので、私は私の作品を追加します:
$var = @{$true="this is true";$false="this is false"}[1 -eq 1]
何よりも醜い!
私は最近PoweShellライブラリ 'Pscx'の三項条件付き演算子とnull合体演算子を改良しました(open PullRequest)。
Plsは私の解決策を探しています。
私のgithubトピックブランチ:tilityModule_Invoke-Operators
Invoke-Ternary
Invoke-TernaryAsPipe
Invoke-NullCoalescing
NullCoalescingAsPipe
Set-Alias :?: Pscx\Invoke-Ternary -Description "PSCX alias"
Set-Alias ?: Pscx\Invoke-TernaryAsPipe -Description "PSCX alias"
Set-Alias :?? Pscx\Invoke-NullCoalescing -Description "PSCX alias"
Set-Alias ?? Pscx\Invoke-NullCoalescingAsPipe -Description "PSCX alias"
<condition_expression> |?: <true_expression> <false_expression>
<variable_expression> |?? <alternate_expression>
式として渡すことができます:
$ null、リテラル、変数、 '外部'式($ b -eq 4)、またはスクリプトブロック{$ b -eq 4}
変数式中の変数が$ nullまたは存在しない場合、代替式は出力として評価されます。
これが代替のカスタム関数アプローチです。
function Test-TernaryOperatorCondition {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true, Mandatory = $true)]
[bool]$ConditionResult
,
[Parameter(Mandatory = $true, Position = 0)]
[PSObject]$ValueIfTrue
,
[Parameter(Mandatory = $true, Position = 1)]
[ValidateSet(':')]
[char]$Colon
,
[Parameter(Mandatory = $true, Position = 2)]
[PSObject]$ValueIfFalse
)
process {
if ($ConditionResult) {
$ValueIfTrue
}
else {
$ValueIfFalse
}
}
}
set-alias -Name '???' -Value 'Test-TernaryOperatorCondition'
例
1 -eq 1 |??? 'match' : 'nomatch'
1 -eq 2 |??? 'match' : 'nomatch'
違いの説明
?
文字は既にWhere-Object
の別名です。??
は他の言語ではnull合体演算子として使われています、そして私は混乱を避けたいと思いました。-2..2 |??? 'match' : 'nomatch'
は、match, match, nomatch, match, match
を与える(すなわち、ゼロでない整数はtrue
と評価されるので、ゼロはfalse
と評価されるため)。([bool](-2..2)) |??? 'match' : 'nomatch'
(または単に[bool](-2..2) |??? 'match' : 'nomatch'
)