140

PowerShellにnull合体演算子はありますか?

これらのc#コマンドをPowerShellで実行できるようにしたいと思います。

var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
4

10 に答える 10

178

Powershell 7+

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式フォームを使用してください。

于 2012-05-17T19:40:39.630 に答える
99

PowerShell7以降

PowerShell 7は多くの新機能を導入し、.NETFrameworkから.NETCoreに移行します。2020年半ばの時点で、.NET Coreに依存しているため、PowerShellのレガシーバージョンを完全に置き換えることはできませんが、Microsoftは、Coreファミリが最終的にレガシーFrameworkファミリを置き換えることを意図していることを示しています。これを読むまでに、互換性のあるバージョンのPowerShellがシステムにプリインストールされている可能性があります。そうでない場合は、https://github.com/powershell/powershellを参照してください。

ドキュメントによると PowerShell7.0では次の演算子がすぐにサポートされます。

  1. ヌル合体??
  2. ヌル合体代入??=
  3. 三元... ? ... : ...

これらは、ヌル合体に期待するとおりに機能します。

$x = $a ?? $b ?? $c ?? 'default value'
$y ??= 'default value'

三項演算子が導入されたため、null合体演算子を追加する必要はありませんが、次のことが可能になりました。

$x = $a -eq $null ? $b : $a

7.0以降、ドキュメント(1、2)で説明されているように、PSNullConditionalOperatorsオプション機能が有効になっている場合は、次のものも使用できます。

  1. メンバーのnull条件付きメンバーアクセス:?.
  2. 配列などのnull条件付きメンバーアクセス:?[]

これらにはいくつかの注意点があります。

  1. これらは実験的なものであるため、変更される可能性があります。これを読んだ時点では、実験的なものとは見なされなくなっている可能性があり、警告のリストが変更されている可能性があります。
  2. ${}変数名には疑問符が使用できるため、実験演算子の1つが後に続く場合は、変数を囲む必要があります。機能が実験的ステータスを卒業するかどうか/いつ卒業するかは不明です(問題#11379を参照)。たとえば${x}?.Test()、new演算子を使用しますが、 。という名前の変数で$x?.Test()実行されます。Test()$x?
  3. ?(TypeScriptから来ている場合、あなたが期待するかもしれないような演算子はありません。以下は機能しません。$x.Test?()

PowerShell6以前

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

説明

この説明は、匿名ユーザーからの編集提案に基づいています。ありがとう、あなたが誰でも!

操作の順序に基づいて、これは次の順序で機能します。

  1. オペレーターは、テストする値の,配列を作成します。
  2. -ne演算子は、指定された値(この場合はnull)に一致するすべての項目を配列から除外します。結果は、ステップ1で作成された配列と同じ順序の非null値の配列です。
  3. [0]フィルター処理された配列の最初の要素を選択するために使用されます。

それを単純化する:

  1. 可能な値の配列を優先順に作成します
  2. 配列からすべてのnull値を除外します
  3. 結果の配列から最初のアイテムを取得します

警告

C#のnull合体演算子とは異なり、最初のステップは配列を作成することであるため、可能なすべての式が評価されます。

于 2013-07-15T06:15:16.653 に答える
15

これは質問の前半に対する答えの半分にすぎないので、必要に応じて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()失敗のリスクを防ぎます。

于 2014-01-03T10:50:03.927 に答える
13

$null, $null, 3 | Select -First 1

戻り値

3

于 2017-10-21T13:24:13.767 に答える
9

Powershell Community Extensions Moduleをインストールすると、次のものを使用できます。

?? Invoke-NullCoalescingのエイリアスです。

$s = ?? {$myval}  {"New Value"}

?:Invoke-Ternaryのエイリアスです。

$x = ?: {$myval -eq $null} {""} {$otherval}
于 2012-05-16T18:07:30.593 に答える
5

最後に、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
于 2019-10-22T16:01:49.573 に答える
4
@($null,$null,"val1","val2",5) | select -First 1
于 2020-02-07T07:17:26.113 に答える
2
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]
 }
于 2012-08-29T00:05:20.147 に答える
2

合体を使用するときは、空の文字列も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)
于 2016-07-15T16:19:33.910 に答える
1

私が得ることができる最も近いものは:$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"

于 2018-09-07T08:59:16.730 に答える