PowerShellにnull合体演算子はありますか?
これらのc#コマンドをPowerShellで実行できるようにしたいと思います。
var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
PowerShellにnull合体演算子はありますか?
これらのc#コマンドをPowerShellで実行できるようにしたいと思います。
var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
Powershell 7では、Powershellにネイティブのヌル合体、ヌル条件付き割り当て、および三項演算子が導入されています。
ヌル合体
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
ヌル条件付き割り当て
$x = $null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
三項演算子
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
Powershell Community Extensionsは必要ありません。式として、標準のPowershellifステートメントを使用できます。
variable = if (condition) { expr1 } else { expr2 }
したがって、最初のC#式の代わりに次のようになります。
var s = myval ?? "new value";
次のいずれかになります(好みに応じて):
$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }
または、$ myvalに含まれる可能性のあるものに応じて、次を使用できます。
$s = if ($myval) { $myval } else { "new value" }
2番目のC#式は、同様の方法でマップされます。
var x = myval == null ? "" : otherval;
になります
$x = if ($myval -eq $null) { "" } else { $otherval }
公平を期すために、これらはそれほどきびきびしておらず、C#フォームほど快適に使用できる場所はありません。
非常に単純な関数でラップして、読みやすくすることも検討してください。
function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
$s = Coalesce $myval "new value"
またはおそらく、IfNull:
function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }
$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval
ご覧のとおり、非常に単純な関数を使用すると、構文をかなり自由に設定できます。
更新:ミックスで考慮すべき追加のオプションの1つは、より一般的なIsTrue関数です。
function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
次に、演算子に少し似ているエイリアスを宣言するPowershellの機能を組み合わせると、次のようになります。
New-Alias "??" Coalesce
$s = ?? $myval "new value"
New-Alias "?:" IfTrue
$ans = ?: ($q -eq "meaning of life") 42 $otherval
明らかに、これはすべての人の好みになるわけではありませんが、あなたが探しているものかもしれません。
Thomasが指摘しているように、C#バージョンと上記のもう1つの微妙な違いは、C#が引数の短絡を実行することですが、関数/エイリアスを含むPowershellバージョンは常にすべての引数を評価します。これが問題になる場合は、if
式フォームを使用してください。
PowerShell 7は多くの新機能を導入し、.NETFrameworkから.NETCoreに移行します。2020年半ばの時点で、.NET Coreに依存しているため、PowerShellのレガシーバージョンを完全に置き換えることはできませんが、Microsoftは、Coreファミリが最終的にレガシーFrameworkファミリを置き換えることを意図していることを示しています。これを読むまでに、互換性のあるバージョンのPowerShellがシステムにプリインストールされている可能性があります。そうでない場合は、https://github.com/powershell/powershellを参照してください。
ドキュメントによると、 PowerShell7.0では次の演算子がすぐにサポートされます。
これらは、ヌル合体に期待するとおりに機能します。
$x = $a ?? $b ?? $c ?? 'default value'
$y ??= 'default value'
三項演算子が導入されたため、null合体演算子を追加する必要はありませんが、次のことが可能になりました。
$x = $a -eq $null ? $b : $a
7.0以降、ドキュメント(1、2)で説明されているように、PSNullConditionalOperators
オプション機能が有効になっている場合は、次のものも使用できます。
?.
?[]
これらにはいくつかの注意点があります。
${}
変数名には疑問符が使用できるため、実験演算子の1つが後に続く場合は、変数を囲む必要があります。機能が実験的ステータスを卒業するかどうか/いつ卒業するかは不明です(問題#11379を参照)。たとえば${x}?.Test()
、new演算子を使用しますが、 。という名前の変数で$x?.Test()
実行されます。Test()
$x?
?(
TypeScriptから来ている場合、あなたが期待するかもしれないような演算子はありません。以下は機能しません。$x.Test?()
7より前のバージョンのPowerShellには、実際のnull合体演算子、または少なくともそのような動作が可能な演算子があります。その演算子は-ne
:
# Format:
# ($a, $b, $c -ne $null)[0]
($null, 'alpha', 1 -ne $null)[0]
# Output:
alpha
null以外のすべての項目の配列を作成するため、null合体演算子よりも少し用途が広いです。
$items = $null, 'alpha', 5, 0, '', @(), $null, $true, $false
$instances = $items -ne $null
[string]::Join(', ', ($instances | ForEach-Object -Process { $_.GetType() }))
# Result:
System.String, System.Int32, System.Int32, System.String, System.Object[],
System.Boolean, System.Boolean
-eq
同様に機能します。これは、nullエントリをカウントするのに役立ちます。
($null, 'a', $null -eq $null).Length
# Result:
2
しかしとにかく、C#の??
演算子をミラーリングする典型的なケースは次のとおりです。
'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output
この説明は、匿名ユーザーからの編集提案に基づいています。ありがとう、あなたが誰でも!
操作の順序に基づいて、これは次の順序で機能します。
,
配列を作成します。-ne
演算子は、指定された値(この場合はnull)に一致するすべての項目を配列から除外します。結果は、ステップ1で作成された配列と同じ順序の非null値の配列です。[0]
フィルター処理された配列の最初の要素を選択するために使用されます。それを単純化する:
C#のnull合体演算子とは異なり、最初のステップは配列を作成することであるため、可能なすべての式が評価されます。
これは質問の前半に対する答えの半分にすぎないので、必要に応じて4分の1の答えになりますが、使用するデフォルト値が実際にはタイプのデフォルト値である場合は、null合体演算子のはるかに簡単な代替手段があります。 :
string s = myval ?? "";
Powershellでは次のように記述できます。
([string]myval)
または
int d = myval ?? 0;
Powershellに変換されます:
([int]myval)
存在しない可能性があり、存在する場合は不要な空白が周囲にある可能性があるxml要素を処理するときに、これらの最初のものが役立つことがわかりました。
$name = ([string]$row.td[0]).Trim()
文字列へのキャストは、要素がnullになるのを防ぎ、Trim()
失敗のリスクを防ぎます。
$null, $null, 3 | Select -First 1
戻り値
3
Powershell Community Extensions Moduleをインストールすると、次のものを使用できます。
?? Invoke-NullCoalescingのエイリアスです。
$s = ?? {$myval} {"New Value"}
?:Invoke-Ternaryのエイリアスです。
$x = ?: {$myval -eq $null} {""} {$otherval}
最後に、PowerShell 7はNull合体代入演算子を取得しました!
PS > $null ?? "a"
a
PS > "x" ?? "y"
x
PS > $x = $null
PS > $x ??= "abc"
PS > $x
abc
PS > $x ??= "xyz"
PS > $x
abc
@($null,$null,"val1","val2",5) | select -First 1
function coalesce {
Param ([string[]]$list)
#$default = $list[-1]
$coalesced = ($list -ne $null)
$coalesced[0]
}
function coalesce_empty { #COALESCE for empty_strings
Param ([string[]]$list)
#$default = $list[-1]
$coalesced = (($list -ne $null) -ne '')[0]
$coalesced[0]
}
合体を使用するときは、空の文字列もnullとして扱う必要があることがよくあります。最終的に、このための関数を作成しました。これは、単純なnull合体の合体にZenexerのソリューションを使用し、次にnullまたは空のチェックにKeith Hillのソリューションを使用し、それをフラグとして追加して、私の関数が両方を実行できるようにしました。
この関数の利点の1つは、例外をスローすることなく、すべての要素をnull(または空)にすることも処理できることです。PowerShellが配列入力を処理する方法のおかげで、任意の多くの入力変数にも使用できます。
function Coalesce([string[]] $StringsToLookThrough, [switch]$EmptyStringAsNull) {
if ($EmptyStringAsNull.IsPresent) {
return ($StringsToLookThrough | Where-Object { $_ } | Select-Object -first 1)
} else {
return (($StringsToLookThrough -ne $null) | Select-Object -first 1)
}
}
これにより、次のテスト結果が生成されます。
Null coallesce tests:
1 (w/o flag) - empty/null/'end' :
1 (with flag) - empty/null/'end' : end
2 (w/o flag) - empty/null :
2 (with flag) - empty/null :
3 (w/o flag) - empty/null/$false/'end' :
3 (with flag) - empty/null/$false/'end' : False
4 (w/o flag) - empty/null/"$false"/'end' :
4 (with flag) - empty/null/"$false"/'end' : False
5 (w/o flag) - empty/'false'/null/"$false"/'end':
5 (with flag) - empty/'false'/null/"$false"/'end': false
テストコード:
Write-Host "Null coalesce tests:"
Write-Host "1 (w/o flag) - empty/null/'end' :" (Coalesce '', $null, 'end')
Write-Host "1 (with flag) - empty/null/'end' :" (Coalesce '', $null, 'end' -EmptyStringAsNull)
Write-Host "2 (w/o flag) - empty/null :" (Coalesce('', $null))
Write-Host "2 (with flag) - empty/null :" (Coalesce('', $null) -EmptyStringAsNull)
Write-Host "3 (w/o flag) - empty/null/`$false/'end' :" (Coalesce '', $null, $false, 'end')
Write-Host "3 (with flag) - empty/null/`$false/'end' :" (Coalesce '', $null, $false, 'end' -EmptyStringAsNull)
Write-Host "4 (w/o flag) - empty/null/`"`$false`"/'end' :" (Coalesce '', $null, "$false", 'end')
Write-Host "4 (with flag) - empty/null/`"`$false`"/'end' :" (Coalesce '', $null, "$false", 'end' -EmptyStringAsNull)
Write-Host "5 (w/o flag) - empty/'false'/null/`"`$false`"/'end':" (Coalesce '', 'false', $null, "$false", 'end')
Write-Host "5 (with flag) - empty/'false'/null/`"`$false`"/'end':" (Coalesce '', 'false', $null, "$false", 'end' -EmptyStringAsNull)
私が得ることができる最も近いものは:$Val = $MyVal |?? "Default Value"
上記のヌル合体演算子を次のように実装しました。
function NullCoalesc {
param (
[Parameter(ValueFromPipeline=$true)]$Value,
[Parameter(Position=0)]$Default
)
if ($Value) { $Value } else { $Default }
}
Set-Alias -Name "??" -Value NullCoalesc
条件付き三項演算子も同様の方法で実装できます。
function ConditionalTernary {
param (
[Parameter(ValueFromPipeline=$true)]$Value,
[Parameter(Position=0)]$First,
[Parameter(Position=1)]$Second
)
if ($Value) { $First } else { $Second }
}
Set-Alias -Name "?:" -Value ConditionalTernary
そして次のように使用されます:$Val = $MyVal |?: $MyVal "Default Value"