web-dev-qa-db-fra.com

Nulle coalescence dans PowerShell

Y at-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;
85
Micah

Pas besoin des extensions de communauté Powershell, vous pouvez utiliser les instructions Powershell standard si en tant qu'expression:

variable = if (condition) { expr1 } else { expr2 }

Voici donc les remplaçants de votre première expression:

var s = myval ?? "new value";

devient l’un des suivants (selon les 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 peut contenir, vous pouvez utiliser:

$s = if ($myval) { $myval } else { "new value" }

et la deuxième expression mappe de la même manière:

var x = myval == null ? "" : otherval;

devient

$x = if ($myval -eq $null) { "" } else { $otherval }

Pour être honnête, elles ne sont pas très vives et ne sont pas aussi confortables à utiliser que les formes 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, si Null:

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 un peu de liberté de syntaxe.

UPDATE: Une option supplémentaire à prendre en compte dans le mix est une fonction IsTrue plus générique:

function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }

$x = IfTrue ($myval -eq $null) "" $otherval

Combinez ensuite la capacité de Powershell à déclarer des alias qui ressemblent un peu à des opérateurs. Vous obtenez ainsi:

New-Alias "??" Coalesce

$s = ?? $myval "new value"

New-Alias "?:" IfTrue

$ans = ?: ($q -eq "meaning of life") 42 $otherval

Il est clair que cela ne plaira pas à tout le monde, mais pourrait être ce que vous cherchez.

100
StephenD

Oui, PowerShell a un opérateur de coalescence nul, ou au moins 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

C'est un peu plus polyvalent qu'un opérateur de coalescence nul, 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 la même manière, 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 l’opérateur ?? de C #:

'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output

Explication

Cette explication est basée sur une suggestion de modification d'un utilisateur anonyme. Merci, qui que vous soyez!

En fonction de l'ordre des opérations, cela fonctionne dans l'ordre suivant:

  1. L'opérateur , crée un tableau de valeurs à tester.
  2. L'opérateur -ne supprime tous les éléments du tableau qui correspondent à la valeur spécifiée - dans le cas présent, null. Le résultat est un tableau de valeurs non NULL dans le même ordre que le tableau créé à l'étape 1.
  3. [0] est utilisé pour sélectionner le premier élément du tableau filtré.

Simplifier cela:

  1. Créer un tableau de valeurs possibles, dans l'ordre préféré
  2. Exclure toutes les valeurs nulles du tableau
  3. Prendre le premier élément du tableau résultant

Mises en garde

Contrairement à l'opérateur de coalescence nul de C #, toutes les expressions possibles seront évaluées, car la première étape consiste à créer un tableau.

76
Zenexer

Il ne s'agit que de la moitié d'une réponse à la première moitié de la question, donc une réponse d'un quart si vous voulez, mais il existe une alternative beaucoup plus simple à l'opérateur de coalescence nulle, à condition que la valeur par défaut que vous souhaitez utiliser soit réellement la valeur par défaut du type :

string s = myval ?? "";

Peut être écrit dans Powershell comme:

([string]myval)

Ou

int d = myval ?? 0;

se traduit par Powershell:

([int]myval)

J'ai trouvé le premier de ces éléments utile lors du traitement d'un élément XML qui pourrait ne pas exister et qui, le cas échéant, pourrait être entouré d'espaces non désirés:

$name = ([string]$row.td[0]).Trim()

Le transtypage en chaîne protège contre la nullité de l'élément et empêche tout risque d'échec de Trim().

12
Duncan

Si vous installez le Powershell Community Extensions Module , vous pouvez utiliser:

?? est l'alias de Invoke-NullCoalescing.

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

?: est le pseudonyme d'Invoke-Ternary.

$x = ?: {$myval -eq $null} {""} {$otherval}
9
EBGreen

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

résultats 

3

5
Chris F Carroll
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]
 }
2
Shawn

Souvent, je constate que je dois également traiter la chaîne vide comme nulle si j'utilise coalesce. J'ai fini par écrire une fonction pour cela, qui utilise la solution de Zenexer pour la fusion de la fusion nulle simple, puis a utilisé Keith Hill pour la vérification nulle ou vide, et l'a ajouté comme indicateur. donc ma fonction pourrait faire les deux.

L'un des avantages de cette fonction est qu'elle gère également le fait d'avoir tous les éléments nuls (ou vides), sans générer d'exception. Il peut également être utilisé pour de nombreuses variables d'entrée arbitraires, grâce à la façon dont PowerShell gère les entrées de tableau.

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)
  }  
}

Cela produit les résultats de test suivants:

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

Code de test:

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)
1
Johny Skovdal

Le plus proche que je puisse obtenir est: $Val = $MyVal |?? "Default Value"

J'ai implémenté l'opérateur de coalescence null comme ci-dessus:

function NullCoalesc {
    param (
        [Parameter(ValueFromPipeline=$true)]$Value,
        [Parameter(Position=0)]$Default
    )

    if ($Value) { $Value } else { $Default }
}

Set-Alias -Name "??" -Value NullCoalesc

L'opérateur ternaire conditionnel pourrait être implémenté de manière similaire.

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

Et utilisé comme: $Val = $MyVal |?: $MyVal "Default Value"

0
Elon Mallin