De ce que je sais, PowerShell ne semble pas avoir d’expression intégrée pour ce que l’on appelle l’opérateur ternary .
Par exemple, dans le langage C, qui supporte l'opérateur ternaire, je pourrais écrire quelque chose comme:
<condition> ? <condition-is-true> : <condition-is-false>;
Si cela n’existe pas vraiment dans PowerShell, quel serait le meilleur moyen (c’est-à-dire facile à lire et à maintenir) d’atteindre le même résultat?
$result = If ($condition) {"true"} Else {"false"}
Tout le reste est une complexité accidentelle et doit donc être évité.
Pour une utilisation dans ou comme expression, pas seulement une affectation, placez-la dans $()
, ainsi:
write-Host $(If ($condition) {"true"} Else {"false"})
La construction PowerShell la plus proche que j'ai pu imaginer est la suivante:
@({'condition is false'},{'condition is true'})[$condition]
Selon ce billet de blog PowerShell , vous pouvez créer un alias pour définir un opérateur ?:
:
set-alias ?: Invoke-Ternary -Option AllScope -Description "PSCX filter alias"
filter Invoke-Ternary ([scriptblock]$decider, [scriptblock]$ifTrue, [scriptblock]$ifFalse)
{
if (&$decider) {
&$ifTrue
} else {
&$ifFalse
}
}
Utilisez-le comme ceci:
$total = ($quantity * $price ) * (?: {$quantity -le 10} {.9} {.75})
Moi aussi, je cherchais une meilleure réponse, et bien que la solution proposée dans le post d’Edward soit "ok", j’ai proposé une solution beaucoup plus naturelle dans ce blog
Court et doux:
# ---------------------------------------------------------------------------
# Name: Invoke-Assignment
# Alias: =
# Author: Garrett Serack (@FearTheCowboy)
# Desc: Enables expressions like the C# operators:
# Ternary:
# <condition> ? <trueresult> : <falseresult>
# e.g.
# status = (age > 50) ? "old" : "young";
# Null-Coalescing
# <value> ?? <value-if-value-is-null>
# e.g.
# name = GetName() ?? "No Name";
#
# Ternary Usage:
# $status == ($age > 50) ? "old" : "young"
#
# Null Coalescing Usage:
# $name = (get-name) ? "No Name"
# ---------------------------------------------------------------------------
# returns the evaluated value of the parameter passed in,
# executing it, if it is a scriptblock
function eval($item) {
if( $item -ne $null ) {
if( $item -is "ScriptBlock" ) {
return & $item
}
return $item
}
return $null
}
# an extended assignment function; implements logic for Ternarys and Null-Coalescing expressions
function Invoke-Assignment {
if( $args ) {
# ternary
if ($p = [array]::IndexOf($args,'?' )+1) {
if (eval($args[0])) {
return eval($args[$p])
}
return eval($args[([array]::IndexOf($args,':',$p))+1])
}
# null-coalescing
if ($p = ([array]::IndexOf($args,'??',$p)+1)) {
if ($result = eval($args[0])) {
return $result
}
return eval($args[$p])
}
# neither ternary or null-coalescing, just a value
return eval($args[0])
}
return $null
}
# alias the function to the equals sign (which doesn't impede the normal use of = )
set-alias = Invoke-Assignment -Option AllScope -Description "FearTheCowboy's Invoke-Assignment."
Ce qui facilite les choses comme (plus d’exemples dans un article de blog):
$message == ($age > 50) ? "Old Man" :"Young Dude"
Puisqu'un opérateur ternaire est généralement utilisé lors de l'attribution de valeur, il devrait renvoyer une valeur. Voici comment cela peut fonctionner:
$var=@("value if false","value if true")[[byte](condition)]
Stupide, mais travaillant. Cette construction peut également être utilisée pour transformer rapidement un int en une autre valeur, il suffit d'ajouter des éléments de tableau et de spécifier une expression qui renvoie des valeurs non négatives basées sur 0.
Essayez l'option commutateur de powershell comme alternative, en particulier pour l'affectation de variable - plusieurs lignes, mais lisible.
Exemple,
$WinVer = switch ( Test-Path $Env:windir\SysWOW64 ) {
$true { "64-bit" }
$false { "32-bit" }
}
"This version of Windows is $WinVer"
Comme je l'ai déjà utilisé plusieurs fois et que je ne le vois pas dans la liste, je vais ajouter mon article:
$var = @{$true="this is true";$false="this is false"}[1 -eq 1]
le plus laid de tous!
J'ai récemment amélioré (Open PullRequest) les opérateurs ternaires conditionnels et à coalescence nulle dans la librairie PoweShell 'Pscx'
Veuillez regarder ma solution.
Ma branche de sujet github:UtilityModule_Invoke-Operators
Invoke-Ternary
Invoke-TernaryAsPipe
Invoke-NullCoalescing
NullCoalescingAsPipe
Set-Alias :?: Pscx\Invoke-Ternary -Description "PSCX alias"
Set-Alias ?: Pscx\Invoke-TernaryAsPipe -Description "PSCX alias"
Set-Alias :?? Pscx\Invoke-NullCoalescing -Description "PSCX alias"
Set-Alias ?? Pscx\Invoke-NullCoalescingAsPipe -Description "PSCX alias"
<condition_expression> |?: <true_expression> <false_expression>
<variable_expression> |?? <alternate_expression>
Comme expression, vous pouvez passer:
$ null, un littéral, une variable, une expression "externe" ($ b -eq 4) ou un scriptblock {$ b -eq 4}
Si une variable dans l'expression de variable est $ null ou inexistante, l'expression alternative est évaluée en tant que sortie.
PowerShell n'a actuellement pas de Inline If (ou ternary If natif, mais vous pouvez envisager d'utiliser l'applet de commande personnalisée:
IIf <condition><condition-is-true><condition-is-false>
Voir: PowerShell Inline If (IIf) } _Voici une approche alternative de la fonction personnalisée:
function Test-TernaryOperatorCondition {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true, Mandatory = $true)]
[bool]$ConditionResult
,
[Parameter(Mandatory = $true, Position = 0)]
[PSObject]$ValueIfTrue
,
[Parameter(Mandatory = $true, Position = 1)]
[ValidateSet(':')]
[char]$Colon
,
[Parameter(Mandatory = $true, Position = 2)]
[PSObject]$ValueIfFalse
)
process {
if ($ConditionResult) {
$ValueIfTrue
}
else {
$ValueIfFalse
}
}
}
set-alias -Name '???' -Value 'Test-TernaryOperatorCondition'
Exemple
1 -eq 1 |??? 'match' : 'nomatch'
1 -eq 2 |??? 'match' : 'nomatch'
Les différences expliquées
?
est déjà un alias pour Where-Object
.??
est utilisé dans d'autres langues en tant qu'opérateur de coalescence nul et je voulais éviter toute confusion.-2..2 |??? 'match' : 'nomatch'
donne: match, match, nomatch, match, match
(c’est-à-dire que tout int différent de zéro est évalué à true
; tandis que zéro correspond à false
.([bool](-2..2)) |??? 'match' : 'nomatch'
(ou simplement: [bool](-2..2) |??? 'match' : 'nomatch'
)