Existe-t-il un opérateur de coalescence nul dans powershell ?
J'aimerais pouvoir faire ces commandes c# dans powershell :
var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
Existe-t-il un opérateur de coalescence nul dans powershell ?
J'aimerais pouvoir faire ces commandes c# dans powershell :
var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
Powershell 7 introduit coalescence native des nuls, affectation conditionnelle des nuls et opérateurs ternaires dans Powershell.
Nulle Coalescence
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
Affectation conditionnelle nulle
$x = $null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
Opérateur ternaire
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
Pas besoin des extensions communautaires Powershell, vous pouvez utiliser les instructions standard Powershell if comme expression :
variable = if (condition) { expr1 } else { expr2 }
Donc aux remplacements pour votre première expression C# de :
var s = myval ?? "new value";
devient l'un des éléments suivants (en fonction des préférences) :
$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }
ou en fonction de ce que $myval pourrait contenir, vous pourriez utiliser :
$s = if ($myval) { $myval } else { "new value" }
et la seconde expression en C# se transforme de manière similaire :
var x = myval == null ? "" : otherval;
devient
$x = if ($myval -eq $null) { "" } else { $otherval }
Pour être honnête, ces formulaires ne sont pas très rapides et sont loin d'être aussi confortables à utiliser que les formulaires C#.
Vous pouvez également envisager de l'envelopper dans une fonction très simple pour rendre les choses plus lisibles :
function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
$s = Coalesce $myval "new value"
ou éventuellement comme, IfNull :
function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }
$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval
Comme vous pouvez le constater, une fonction très simple peut vous donner une grande liberté de syntaxe.
MISE À JOUR : Une option supplémentaire à considérer dans le mélange est une fonction IsTrue plus générique :
function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
Si l'on combine cela avec la capacité de Powershell à déclarer des alias qui ressemblent un peu à des opérateurs, on obtient.. :
New-Alias "??" Coalesce
$s = ?? $myval "new value"
New-Alias "?:" IfTrue
$ans = ?: ($q -eq "meaning of life") 42 $otherval
Il est évident que cela ne sera pas du goût de tout le monde, mais cela peut correspondre à ce que vous recherchez.
Comme le note Thomas, une autre différence subtile entre la version C# et la précédente est que C# effectue un court-circuitage des arguments, mais les versions Powershell impliquant des fonctions/aliases évalueront toujours tous les arguments. Si cela pose un problème, utilisez l'option if
forme d'expression.
Le seul véritable équivalent de l'opérateur de coalescence est l'utilisation d'une instruction if ; le problème est que toute autre approche évalue tous les opérandes au lieu de les court-circuiter. L'expression " ?? $myval SomeReallyExpenisveFunction()" appellera la fonction même si $myval n'est pas nul. Je suppose que l'on pourrait retarder l'évaluation en utilisant des blocs de script, mais il faut savoir que les blocs de script ne sont PAS des fermetures, et que les choses commencent à devenir compliquées.
Ne fonctionne pas en mode strict -- il lance The variable '$myval' cannot be retrieved because it has not been set.
.
@BrainSlugs83 L'erreur que vous rencontrez en mode strict n'est pas liée aux options de coalescence des nullités présentées. Il s'agit simplement du contrôle standard de Powershell qui vérifie qu'une variable est définie en premier. Si vous définissez $myval = $null
avant d'effectuer le test, l'erreur devrait disparaître.
PowerShell 7 introduit de nombreuses nouvelles fonctionnalités et migre de .NET Framework vers .NET Core. À la mi-2020, il n'a pas encore complètement remplacé les anciennes versions de PowerShell en raison de la dépendance à l'égard de .NET Core, mais Microsoft a indiqué que la famille Core avait l'intention de remplacer à terme la famille Framework. Au moment où vous lirez ces lignes, une version compatible de PowerShell sera peut-être préinstallée sur votre système. https://github.com/powershell/powershell .
Par la documentation Les opérateurs suivants sont pris en charge dès le départ dans PowerShell 7.0 :
??
??=
... ? ... : ...
Ils fonctionnent comme on peut s'y attendre pour une coalescence nulle :
$x = $a ?? $b ?? $c ?? 'default value'
$y ??= 'default value'
Depuis qu'un opérateur ternaire a été introduit, ce qui suit est maintenant possible, bien que cela soit inutile étant donné l'ajout d'un opérateur de coalescence nul :
$x = $a -eq $null ? $b : $a
À partir de la version 7.0, les éléments suivants sont également disponibles si l'option PSNullConditionalOperators
La fonction optionnelle est activé comme expliqué dans la documentation ( 1 , 2 ) :
?.
?[]
Celles-ci comportent quelques mises en garde :
${}
s'il est suivi par l'un des opérateurs expérimentaux, car les points d'interrogation sont autorisés dans les noms de variables. Il n'est pas clair si cela sera le cas si/quand les fonctionnalités passeront du statut expérimental (cf. numéro 11379 ). Par exemple, ${x}?.Test()
utilise le nouvel opérateur, mais $x?.Test()
exécute Test()
sur une variable nommée $x?
.?(
comme vous pouvez vous y attendre si vous venez de TypeScript. Ce qui suit ne fonctionnera pas : $x.Test?()
Les versions de PowerShell antérieures à 7 disposent d'un opérateur de coalescence des nullités, ou du moins d'un opérateur capable d'un tel comportement. Cet opérateur est -ne
:
# Format:
# ($a, $b, $c -ne $null)[0]
($null, 'alpha', 1 -ne $null)[0]
# Output:
alpha
Il est un peu plus polyvalent qu'un opérateur de coalescence des éléments nuls, puisqu'il crée un tableau de tous les éléments non nuls :
$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
fonctionne de manière similaire, ce qui est utile pour compter les entrées nulles :
($null, 'a', $null -eq $null).Length
# Result:
2
Quoi qu'il en soit, voici un cas typique qui reflète celui du C#. ??
opérateur :
'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output
Cette explication est basée sur une suggestion d'édition d'un utilisateur anonyme. Merci, qui que vous soyez !
En se basant sur l'ordre des opérations, cela fonctionne dans l'ordre suivant :
,
L'opérateur crée un tableau de valeurs à tester.-ne
filtre tous les éléments du tableau qui correspondent à la valeur spécifiée - dans ce cas, null. Le résultat est un tableau de valeurs non nulles dans le même ordre que le tableau créé à l'étape 1.[0]
est utilisé pour sélectionner le premier élément du tableau filtré.Simplifier cela :
Contrairement à l'opérateur null coalescing du C#, toutes les expressions possibles seront évaluées, puisque la première étape consiste à créer un tableau.
J'ai fini par utiliser une version modifiée de votre réponse dans la mienne car j'avais besoin de permettre à toutes les instances de la coalescence d'être nulles, sans lever d'exception. Mais c'est une très bonne façon de faire, qui m'a beaucoup appris :)
Cette méthode permet d'éviter les courts-circuits. Définir function DidItRun($a) { Write-Host "It ran with $a"; return $a }
et exécuter ((DidItRun $null), (DidItRun 'alpha'), 1 -ne $null)[0]
pour voir ceci.
Ce n'est qu'une demi réponse à la première moitié de la question, donc un quart de réponse si vous voulez, mais il existe une alternative beaucoup plus simple à l'opérateur de coalescence nul, à condition que la valeur par défaut que vous voulez utiliser soit effectivement la valeur par défaut du type :
string s = myval ?? "";
Peut être écrit en Powershell comme :
([string]myval)
Ou
int d = myval ?? 0;
traduit en Powershell :
([int]myval)
J'ai trouvé la première utile lors du traitement d'un élément xml qui pourrait ne pas exister et qui, s'il existait, pourrait avoir un espace blanc indésirable autour de lui :
$name = ([string]$row.td[0]).Trim()
Le passage à une chaîne de caractères protège l'élément contre la nullité et évite tout risque de conflit entre les deux éléments. Trim()
à défaut.
Si vous installez le Module d'extension de la communauté Powershell alors vous pouvez utiliser :
? ?? est l'alias de Invoke-NullCoalescing.
$s = ?? {$myval} {"New Value"}
? : est l'alias de Invoke-Ternary.
$x = ?: {$myval -eq $null} {""} {$otherval}
En fait, ce ne sont pas des commandes PowerShell. Vous les avez eu ensemble avec pscx : ? : -> Invoke-Ternary
... a manqué le code réel et le résultat.. ;) Get-Command -Module pscx -CommandType alias | where { $_.Name -match '\ ?.' } | foreach { "{0} : {1}" -f $_.Name, $_.Definition } ? : : Invoke-Ternary ?? : : Invoke-NullCoalescing
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.