Antworten:
Powershell 7 führt in Powershell native Null-Koaleszenz-, Null-Bedingungszuweisungs- und ternäre Operatoren ein.
Null-Koaleszenz
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
Null bedingte Zuweisung
$x = $null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
Ternärer Operator
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
Sie benötigen keine Powershell-Community-Erweiterungen. Sie können die Standard-Powershell-if-Anweisungen als Ausdruck verwenden:
variable = if (condition) { expr1 } else { expr2 }
Also zu den Ersetzungen für Ihren ersten C # -Ausdruck von:
var s = myval ?? "new value";
wird einer der folgenden (je nach Präferenz):
$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }
oder je nachdem, was $ myval enthalten könnte, könnten Sie verwenden:
$s = if ($myval) { $myval } else { "new value" }
und der zweite C # -Ausdruck wird auf ähnliche Weise abgebildet:
var x = myval == null ? "" : otherval;
wird
$x = if ($myval -eq $null) { "" } else { $otherval }
Nun, um fair zu sein, diese sind nicht sehr bissig und bei weitem nicht so bequem zu bedienen wie die C # -Formulare.
Sie können es auch in eine sehr einfache Funktion einbinden, um die Lesbarkeit zu verbessern:
function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
$s = Coalesce $myval "new value"
oder möglicherweise als IfNull:
function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }
$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval
Wie Sie sehen, kann eine sehr einfache Funktion Ihnen einiges an Syntaxfreiheit geben.
UPDATE: Eine zusätzliche Option, die im Mix berücksichtigt werden muss, ist eine allgemeinere IsTrue-Funktion:
function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
Kombinieren Sie dann die Fähigkeit von Powershell, Aliase zu deklarieren, die ein bisschen wie Operatoren aussehen. Am Ende haben Sie:
New-Alias "??" Coalesce
$s = ?? $myval "new value"
New-Alias "?:" IfTrue
$ans = ?: ($q -eq "meaning of life") 42 $otherval
Natürlich wird dies nicht jedermanns Geschmack sein, aber es könnte das sein, wonach Sie suchen.
Wie Thomas bemerkt, besteht ein weiterer subtiler Unterschied zwischen der C # -Version und der obigen darin, dass C # die Argumente kurzschließt, aber die Powershell-Versionen, die Funktionen / Aliase enthalten, bewerten immer alle Argumente. Wenn dies ein Problem ist, verwenden Sie das if
Ausdrucksformular.
The variable '$myval' cannot be retrieved because it has not been set.
.
$myval = $null
vor dem Test festlegen , sollte der Fehler behoben sein.
$null -ne $a
kann jetzt keine anständige Referenz finden, ist aber eine langjährige Praxis.
PowerShell 7 führt viele neue Funktionen ein und migriert von .NET Framework zu .NET Core. Ab Mitte 2020 wurden ältere Versionen von PowerShell aufgrund der Abhängigkeit von .NET Core nicht vollständig ersetzt. Microsoft hat jedoch angegeben, dass die Core-Familie die ältere Framework-Familie ersetzen soll. Wenn Sie dies lesen, ist möglicherweise eine kompatible Version von PowerShell auf Ihrem System vorinstalliert. Wenn nicht, siehe https://github.com/powershell/powershell .
Gemäß der Dokumentation werden die folgenden Operatoren in PowerShell 7.0 sofort unterstützt:
??
??=
... ? ... : ...
Diese funktionieren wie erwartet für eine Null-Koaleszenz:
$x = $a ?? $b ?? $c ?? 'default value'
$y ??= 'default value'
Da ein ternärer Operator eingeführt wurde, ist jetzt Folgendes möglich, obwohl dies angesichts der Hinzufügung eines Null-Koaleszenzoperators nicht erforderlich ist:
$x = $a -eq $null ? $b : $a
Ab 7.0 ist auch Folgendes verfügbar, wenn die PSNullConditionalOperators
optionale Funktion aktiviert ist , wie in den Dokumenten ( 1 , 2 ) erläutert :
?.
?[]
Diese haben ein paar Einschränkungen:
${}
wenn sie von einem der experimentellen Operatoren befolgt werden, da Fragezeichen in Variablennamen zulässig sind. Es ist unklar, ob dies der Fall sein wird, wenn / wenn die Merkmale den experimentellen Status verlassen (siehe Ausgabe Nr. 11379 ). Zum Beispiel ${x}?.Test()
verwendet die neuen Betreiber, sondern $x?.Test()
läuft Test()
auf eine Variable mit dem Namen $x?
.?(
Operator, wie Sie vielleicht erwarten, wenn Sie von TypeScript kommen. Folgendes wird nicht funktionieren:$x.Test?()
PowerShell-Versionen vor 7 haben einen tatsächlichen Null-Koaleszenz-Operator oder zumindest einen Operator, der zu einem solchen Verhalten fähig ist. Dieser Operator ist -ne
:
# Format:
# ($a, $b, $c -ne $null)[0]
($null, 'alpha', 1 -ne $null)[0]
# Output:
alpha
Es ist etwas vielseitiger als ein Null-Koaleszenz-Operator, da es ein Array aller Nicht-Null-Elemente erstellt:
$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
funktioniert ähnlich, was zum Zählen von Null-Einträgen nützlich ist:
($null, 'a', $null -eq $null).Length
# Result:
2
Aber hier ist ein typischer Fall, um den ??
Operator von C # zu spiegeln :
'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output
Diese Erklärung basiert auf einem Bearbeitungsvorschlag eines anonymen Benutzers. Danke, wer auch immer du bist!
Basierend auf der Reihenfolge der Operationen funktioniert dies in der folgenden Reihenfolge:
,
Operator erstellt ein Array von zu testenden Werten.-ne
Operator filtert alle Elemente aus dem Array heraus, die dem angegebenen Wert entsprechen - in diesem Fall null. Das Ergebnis ist ein Array von Nicht-Null-Werten in derselben Reihenfolge wie das in Schritt 1 erstellte Array.[0]
wird verwendet, um das erste Element des gefilterten Arrays auszuwählen.Vereinfachung:
Im Gegensatz zum Null-Koaleszenz-Operator von C # wird jeder mögliche Ausdruck ausgewertet, da der erste Schritt darin besteht, ein Array zu erstellen.
function DidItRun($a) { Write-Host "It ran with $a"; return $a }
und ausführen ((DidItRun $null), (DidItRun 'alpha'), 1 -ne $null)[0]
, um dies zu sehen.
,
eine so hohe Priorität hat. Für alle, die sich nicht sicher sind, wie das funktioniert, ($null, 'alpha', 1 -ne $null)[0]
ist es dasselbe wie (($null, 'alpha', 1) -ne $null)[0]
. Tatsächlich sind -split
und -join
(und unäre Striche ? Dh -4
oder -'56'
) die einzigen zwei "Strich" -Operatoren mit höherer Priorität .
Dies ist nur eine halbe Antwort auf die erste Hälfte der Frage, also eine viertel Antwort, wenn Sie so wollen, aber es gibt eine viel einfachere Alternative zum Null-Koaleszenz-Operator, vorausgesetzt, der Standardwert, den Sie verwenden möchten, ist tatsächlich der Standardwert für den Typ ::
string s = myval ?? "";
Kann in Powershell geschrieben werden als:
([string]myval)
Oder
int d = myval ?? 0;
übersetzt in Powershell:
([int]myval)
Ich fand das erste davon nützlich, wenn ich ein XML-Element verarbeite, das möglicherweise nicht vorhanden ist und das, falls vorhanden, unerwünschte Leerzeichen enthält:
$name = ([string]$row.td[0]).Trim()
Der Cast-to-String schützt vor dem Null-Element und verhindert das Risiko eines Ausfalls Trim()
.
([string]$null)
-> ""
scheint ein "nützlicher, aber unglücklicher Nebeneffekt" zu sein :(
$null, $null, 3 | Select -First 1
kehrt zurück
3
Wenn Sie das Powershell Community Extensions-Modul installieren, können Sie Folgendes verwenden:
?? ist der Alias für Invoke-NullCoalescing.
$s = ?? {$myval} {"New Value"}
?: ist der Alias für Invoke-Ternary.
$x = ?: {$myval -eq $null} {""} {$otherval}
Schließlich hat PowerShell 7 Null Coalescing-Zuweisungsoperatoren !
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
Oft stelle ich fest, dass ich leere Zeichenfolgen auch als Null behandeln muss, wenn ich Coalesce verwende. Am Ende habe ich eine Funktion dafür geschrieben, die Zenexers Lösung zum Zusammenführen für die einfache Null-Zusammenführung verwendet, und dann Keith Hills für die Null- oder Leerprüfung verwendet, und diese als Flag hinzugefügt, damit meine Funktion beides kann.
Einer der Vorteile dieser Funktion besteht darin, dass alle Elemente null (oder leer) sind, ohne eine Ausnahme auszulösen. Dank der Verarbeitung von Array-Eingaben durch PowerShell kann es auch für beliebig viele Eingabevariablen verwendet werden.
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)
}
}
Dies führt zu folgenden Testergebnissen:
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
Testcode:
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)
Am nächsten kann ich kommen: $Val = $MyVal |?? "Default Value"
Ich habe den Null-Koaleszenz-Operator für das Folgende wie folgt implementiert :
function NullCoalesc {
param (
[Parameter(ValueFromPipeline=$true)]$Value,
[Parameter(Position=0)]$Default
)
if ($Value) { $Value } else { $Default }
}
Set-Alias -Name "??" -Value NullCoalesc
Der bedingte ternäre Operator könnte auf ähnliche Weise implementiert werden.
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
Und verwendet wie: $Val = $MyVal |?: $MyVal "Default Value"