Risposte:
Powershell 7 introduce la coalescenza null nativa, l'assegnazione condizionale null e gli operatori ternari in Powershell.
Null Coalescing
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
Assegnazione condizionale nulla
$x = $null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
Operatore ternario
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
Non sono necessarie le estensioni della community di Powershell, puoi utilizzare le istruzioni if standard di Powershell come espressione:
variable = if (condition) { expr1 } else { expr2 }
Quindi, alle sostituzioni per la tua prima espressione C # di:
var s = myval ?? "new value";
diventa uno dei seguenti (a seconda delle preferenze):
$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }
oa seconda di cosa potrebbe contenere $ myval potresti usare:
$s = if ($myval) { $myval } else { "new value" }
e la seconda espressione C # esegue la mappatura in modo simile:
var x = myval == null ? "" : otherval;
diventa
$x = if ($myval -eq $null) { "" } else { $otherval }
Per essere onesti, questi non sono molto scattanti e non sono neanche lontanamente comodi da usare come i moduli C #.
Potresti anche considerare di avvolgerlo in una funzione molto semplice per rendere le cose più leggibili:
function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
$s = Coalesce $myval "new value"
o eventualmente come IfNull:
function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }
$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval
Come puoi vedere una funzione molto semplice può darti un po 'di libertà di sintassi.
AGGIORNAMENTO: un'opzione extra da considerare nel mix è una funzione IsTrue più generica:
function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
Quindi combinare questa è la capacità di Powershell di dichiarare alias che assomigliano un po 'agli operatori, si finisce con:
New-Alias "??" Coalesce
$s = ?? $myval "new value"
New-Alias "?:" IfTrue
$ans = ?: ($q -eq "meaning of life") 42 $otherval
Chiaramente questo non sarà per tutti i gusti, ma potrebbe essere quello che stai cercando.
Come nota Thomas, un'altra sottile differenza tra la versione C # e quella precedente è che C # esegue il cortocircuito degli argomenti, ma le versioni di Powershell che coinvolgono funzioni / alias valuteranno sempre tutti gli argomenti. Se questo è un problema, usa il if
modulo dell'espressione.
The variable '$myval' cannot be retrieved because it has not been set.
.
$myval = $null
prima di eseguire il test, l'errore dovrebbe scomparire.
$null -ne $a
Non riesco a trovare un riferimento decente ora, ma è una pratica di vecchia data.
PowerShell 7 introduce molte nuove funzionalità e migra da .NET Framework a .NET Core. A partire dalla metà del 2020, non ha completamente sostituito le versioni legacy di PowerShell a causa della dipendenza da .NET Core, ma Microsoft ha indicato che intende che la famiglia Core sostituisca alla fine la famiglia Framework legacy. Nel momento in cui leggi questo, una versione compatibile di PowerShell potrebbe essere preinstallata sul tuo sistema; in caso contrario, vedere https://github.com/powershell/powershell .
Secondo la documentazione , i seguenti operatori sono supportati out-of-the-box in PowerShell 7.0:
??
??=
... ? ... : ...
Funzionano come ci si aspetterebbe per la coalescenza nulla:
$x = $a ?? $b ?? $c ?? 'default value'
$y ??= 'default value'
Poiché è stato introdotto un operatore ternario, ora è possibile quanto segue, sebbene non sia necessario data l'aggiunta di un operatore di coalescenza nullo:
$x = $a -eq $null ? $b : $a
A partire dalla versione 7.0, sono disponibili anche i seguenti se la PSNullConditionalOperators
funzione opzionale è abilitata , come spiegato nei documenti ( 1 , 2 ):
?.
?[]
Questi hanno alcuni avvertimenti:
${}
se seguite da uno degli operatori sperimentali perché i punti interrogativi sono consentiti nei nomi delle variabili. Non è chiaro se questo sarà il caso se / quando le funzionalità passeranno dallo stato sperimentale (vedi problema # 11379 ). Ad esempio, ${x}?.Test()
utilizza l'operatore new, ma $x?.Test()
viene eseguito Test()
su una variabile denominata $x?
.?(
operatore come ci si potrebbe aspettare se si proviene da TypeScript. Quanto segue non funzionerà:$x.Test?()
Le versioni di PowerShell precedenti alla 7 hanno un operatore di coalescenza null effettivo o almeno un operatore in grado di eseguire tale comportamento. Quell'operatore è -ne
:
# Format:
# ($a, $b, $c -ne $null)[0]
($null, 'alpha', 1 -ne $null)[0]
# Output:
alpha
È un po 'più versatile di un operatore di coalescenza nullo, poiché crea un array di tutti gli elementi non nulli:
$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
funziona in modo simile, il che è utile per contare le voci nulle:
($null, 'a', $null -eq $null).Length
# Result:
2
Comunque, ecco un caso tipico per rispecchiare l' ??
operatore di C # :
'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output
Questa spiegazione si basa su un suggerimento di modifica di un utente anonimo. Grazie, chiunque tu sia!
In base all'ordine delle operazioni, funziona nel seguente ordine:
,
operatore crea un array di valori da testare.-ne
operatore filtra tutti gli elementi dall'array che corrispondono al valore specificato, in questo caso null. Il risultato è una matrice di valori non nulli nello stesso ordine della matrice creata nel passaggio 1.[0]
viene utilizzato per selezionare il primo elemento della matrice filtrata.Semplificando che:
A differenza dell'operatore di coalescenza null di C #, verrà valutata ogni possibile espressione, poiché il primo passaggio consiste nel creare un array.
function DidItRun($a) { Write-Host "It ran with $a"; return $a }
e corri ((DidItRun $null), (DidItRun 'alpha'), 1 -ne $null)[0]
per vederlo.
,
ha una precedenza così alta. Per chiunque sia confuso su come funziona, ($null, 'alpha', 1 -ne $null)[0]
è lo stesso di (($null, 'alpha', 1) -ne $null)[0]
. Infatti gli unici due operatori "trattino" con maggiore precendenza sono -split
e -join
(e trattino unario? Ie . -4
O -'56'
).
Questa è solo una mezza risposta alla prima metà della domanda, quindi un quarto di risposta se vuoi, ma esiste un'alternativa molto più semplice all'operatore di coalescenza nullo a condizione che il valore predefinito che desideri utilizzare sia effettivamente il valore predefinito per il tipo :
string s = myval ?? "";
Può essere scritto in Powershell come:
([string]myval)
O
int d = myval ?? 0;
si traduce in Powershell:
([int]myval)
Ho trovato il primo di questi utile durante l'elaborazione di un elemento xml che potrebbe non esistere e che, se esistesse, potrebbe contenere spazi vuoti indesiderati attorno ad esso:
$name = ([string]$row.td[0]).Trim()
Il cast su stringa protegge dall'elemento null e previene qualsiasi rischio di Trim()
errore.
([string]$null)
-> ""
sembra un "effetto collaterale utile ma sfortunato" :(
$null, $null, 3 | Select -First 1
ritorna
3
Se installi il Powershell Community Extensions Module , puoi utilizzare:
?? è l'alias per Invoke-NullCoalescing.
$s = ?? {$myval} {"New Value"}
?: è l'alias di Invoke-Ternary.
$x = ?: {$myval -eq $null} {""} {$otherval}
Infine, PowerShell 7 ha ottenuto gli operatori di assegnazione Null Coalescing !
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
Spesso trovo che devo anche trattare la stringa vuota come nulla quando utilizzo il coalesce. Ho finito per scrivere una funzione per questo, che utilizza la soluzione di Zenexer per il coalescing per il semplice null coalesce, quindi ho usato Keith Hill per il controllo null o vuoto, aggiungendo quello come flag in modo che la mia funzione potesse fare entrambe le cose.
Uno dei vantaggi di questa funzione è che gestisce anche tutti gli elementi null (o vuoti), senza generare eccezioni. Può anche essere utilizzato per molte variabili di input arbitrarie, grazie al modo in cui PowerShell gestisce gli input degli array.
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)
}
}
Questo produce i seguenti risultati del test:
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
Codice di prova:
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)
Il più vicino che posso ottenere è: $Val = $MyVal |?? "Default Value"
Ho implementato l' operatore di coalescenza nullo per quanto sopra in questo modo:
function NullCoalesc {
param (
[Parameter(ValueFromPipeline=$true)]$Value,
[Parameter(Position=0)]$Default
)
if ($Value) { $Value } else { $Default }
}
Set-Alias -Name "??" -Value NullCoalesc
L' operatore ternario condizionale potrebbe essere implementato in modo simile.
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
E usato come: $Val = $MyVal |?: $MyVal "Default Value"