Soweit ich weiß, scheint PowerShell keinen eingebauten Ausdruck für den sogenannten ternären Operator zu haben.
In der C-Sprache, die den ternären Operator unterstützt, könnte ich beispielsweise Folgendes schreiben:
<condition> ? <condition-is-true> : <condition-is-false>;
Wenn dies in PowerShell nicht wirklich vorhanden ist, was wäre der beste Weg (d. H. Einfach zu lesen und zu warten), um dasselbe Ergebnis zu erzielen?
$result = If ($condition) {"true"} Else {"false"}
Alles andere ist zufällige Komplexität und sollte daher vermieden werden.
Um in oder als Ausdruck und nicht nur als Zuweisung zu verwenden, packen Sie es in $()
, also:
write-Host $(If ($condition) {"true"} Else {"false"})
Das nächstgelegene PowerShell-Konstrukt, zu dem ich emulieren konnte, lautet:
@({'condition is false'},{'condition is true'})[$condition]
Mit diesem PowerShell-Blogpost können Sie einen Alias erstellen, um einen ?:
-Operator zu definieren:
set-alias ?: Invoke-Ternary -Option AllScope -Description "PSCX filter alias"
filter Invoke-Ternary ([scriptblock]$decider, [scriptblock]$ifTrue, [scriptblock]$ifFalse)
{
if (&$decider) {
&$ifTrue
} else {
&$ifFalse
}
}
Verwenden Sie es so:
$total = ($quantity * $price ) * (?: {$quantity -le 10} {.9} {.75})
Ich suchte auch nach einer besseren Antwort, und während die Lösung in Edwards Beitrag "ok" ist, habe ich in diesem Blogbeitrag eine viel natürlichere Lösung gefunden
Kurz und bündig:
# ---------------------------------------------------------------------------
# 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."
Das macht es einfach, Dinge zu tun wie (mehr Beispiele im Blog-Post):
$message == ($age > 50) ? "Old Man" :"Young Dude"
Da bei der Zuweisung von Werten normalerweise ein ternärer Operator verwendet wird, sollte er einen Wert zurückgeben. So kann das funktionieren:
[email protected]("value if false","value if true")[[byte](condition)]
Dumm, aber funktionierte. Diese Konstruktion kann auch verwendet werden, um ein int schnell in einen anderen Wert umzuwandeln. Fügen Sie einfach Arrayelemente hinzu und geben Sie einen Ausdruck an, der 0-basierte nicht negative Werte zurückgibt.
Versuchen Sie die switch - Anweisung von powershell als Alternative, insbesondere für die variable Zuweisung - mehrere Zeilen, aber lesbar.
Beispiel,
$WinVer = switch ( Test-Path $Env:windir\SysWOW64 ) {
$true { "64-bit" }
$false { "32-bit" }
}
"This version of Windows is $WinVer"
Da ich dies schon viele Male verwendet habe und es hier nicht aufgeführt habe, füge ich mein Stück hinzu:
$var = @{$true="this is true";$false="this is false"}[1 -eq 1]
am hässlichsten von allen!
Ich habe kürzlich die ternären bedingten und nullkoaleszierenden Operatoren in der PoweShell-Bibliothek 'Pscx' verbessert (open PullRequest).
Bitte schauen Sie nach meiner Lösung.
Mein Zweig für github-Themen: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>
Als Ausdruck kannst du weitergeben:
$ null, ein Literal, eine Variable, ein 'externer' Ausdruck ($ b - eq 4) oder ein Skriptblock {$ b - eq 4}
Wenn eine Variable im Variablenausdruck $ null ist oder nicht vorhanden ist, wird der alternative Ausdruck als Ausgabe ausgewertet.
PowerShell verfügt derzeit nicht über ein systemeigenes Inline-If (oder ternary If ). Sie könnten jedoch das benutzerdefinierte Cmdlet verwenden:
IIf <condition><condition-is-true><condition-is-false>
Siehe: PowerShell Inline If (IIf)Hier ist ein alternativer Ansatz für benutzerdefinierte Funktionen:
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'
Beispiel
1 -eq 1 |??? 'match' : 'nomatch'
1 -eq 2 |??? 'match' : 'nomatch'
Unterschiede erklärt
?
ist bereits ein Alias für Where-Object
.??
wird in anderen Sprachen als nullkoaleszierender Operator verwendet, und ich wollte Verwirrung vermeiden.-2..2 |??? 'match' : 'nomatch'
ergibt: match, match, nomatch, match, match
(d. h., da ein beliebiges Nicht-Zero int zu true
ausgewertet wird, während null zu false
auswertet).([bool](-2..2)) |??? 'match' : 'nomatch'
(oder einfach: [bool](-2..2) |??? 'match' : 'nomatch'
)