Yanıtlar:
Powershell 7, Powershell'de yerel boş birleştirme, boş koşullu atama ve üçlü operatörler sunar.
Boş Birleştirme
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
Boş Koşullu Atama
$x = $null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
Üçlü operatör
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
Powershell Topluluk Uzantılarına gerek yok, ifadeler bir ifade olarak aşağıdaki durumlarda standart Powershell'i kullanabilirsiniz:
variable = if (condition) { expr1 } else { expr2 }
İlk C # ifadenizin yerine geçecek:
var s = myval ?? "new value";
aşağıdakilerden biri olur (tercihe bağlı olarak):
$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }
veya kullanabileceğiniz $ myval içeriğine bağlı olarak:
$s = if ($myval) { $myval } else { "new value" }
ve ikinci C # ifadesi benzer şekilde eşlenir:
var x = myval == null ? "" : otherval;
olur
$x = if ($myval -eq $null) { "" } else { $otherval }
Şimdi adil olmak gerekirse, bunlar çok çabuk değil ve C # formları kadar rahat kullanılamazlar.
Ayrıca, her şeyi daha okunaklı hale getirmek için çok basit bir işleve sarmayı düşünebilirsiniz:
function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
$s = Coalesce $myval "new value"
veya muhtemelen IfNull:
function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }
$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval
Gördüğünüz gibi, çok basit bir işlev size biraz sözdizimi özgürlüğü verebilir.
GÜNCELLEME: Karışımda dikkate alınması gereken fazladan bir seçenek, daha genel bir IsTrue işlevidir:
function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
Daha sonra, Powershell'in operatörlere biraz benzeyen takma adlar beyan etme yeteneğini birleştirin, sonunda:
New-Alias "??" Coalesce
$s = ?? $myval "new value"
New-Alias "?:" IfTrue
$ans = ?: ($q -eq "meaning of life") 42 $otherval
Açıkçası bu herkesin zevkine uygun olmayacak, ama aradığınız şey olabilir.
Thomas'ın belirttiği gibi, C # sürümü ile yukarıdakiler arasındaki bir diğer ince fark, C # 'nın bağımsız değişkenleri kısa devre yaptırmasıdır, ancak işlevleri / diğer adları içeren Powershell sürümleri her zaman tüm bağımsız değişkenleri değerlendirecektir. Bu bir sorunsa, if
ifade formunu kullanın .
The variable '$myval' cannot be retrieved because it has not been set.
.
$myval = $null
Testi yapmadan önce ayarlarsanız , hatanın ortadan kalkması gerekir.
$null -ne $a
şu anda düzgün bir referans bulamıyorum, ancak uzun süredir devam eden bir uygulamadır.
PowerShell 7 birçok yeni özellik sunar ve .NET Framework'ten .NET Core'a geçiş yapar. 2020 ortalarından itibaren, .NET Core'a güvenilmesi nedeniyle PowerShell'in eski sürümlerini tamamen değiştirmedi, ancak Microsoft, Core ailesinin nihayetinde eski Framework ailesini değiştirmeyi planladığını belirtti. Bunu okuduğunuzda, PowerShell'in uyumlu bir sürümü sisteminize önceden yüklenmiş olarak gelebilir; değilse, bkz. https://github.com/powershell/powershell .
Başına belgelerine aşağıdaki operatörler dışı-box PowerShell 7.0 desteklenir:
??
??=
... ? ... : ...
Bunlar boş birleştirme için beklediğiniz gibi çalışır:
$x = $a ?? $b ?? $c ?? 'default value'
$y ??= 'default value'
Üçlü bir operatör tanıtıldığından, artık bir boş birleştirme operatörü eklendiğinde gereksiz olsa da aşağıdakiler mümkündür:
$x = $a -eq $null ? $b : $a
7.0'dan itibaren, PSNullConditionalOperators
isteğe bağlı özellik etkinleştirilirse , belgelerde ( 1 , 2 ) açıklandığı gibi aşağıdakiler de mevcuttur :
?.
?[]
Bunların birkaç uyarısı var:
${}
adlarında soru işaretlerine izin verildiğinden, değişkenler deneysel operatörlerden biri tarafından takip ediliyorsa, içine alınmalıdır . Özelliklerin deneysel durumdan mezun olması durumunda durumun bu olup olmayacağı belirsizdir (bkz. Sorun # 11379 ). Örneğin ${x}?.Test()
, yeni operatörü kullanır, ancak adlı bir değişken üzerinde $x?.Test()
çalışır .Test()
$x?
?(
TypeScript'ten geliyorsanız beklediğiniz gibi bir operatör yoktur . Aşağıdakiler işe yaramaz:$x.Test?()
7'den önceki PowerShell sürümlerinde gerçek bir boş birleştirme operatörü veya en azından bu tür davranışları gerçekleştirebilen bir operatör vardır. Bu operatör -ne
:
# Format:
# ($a, $b, $c -ne $null)[0]
($null, 'alpha', 1 -ne $null)[0]
# Output:
alpha
Boş birleştirme operatöründen biraz daha çok yönlüdür çünkü boş olmayan tüm öğelerden oluşan bir dizi oluşturur:
$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
benzer şekilde çalışır, bu da boş girdileri saymak için kullanışlıdır:
($null, 'a', $null -eq $null).Length
# Result:
2
Her neyse, işte C # ??
operatörünü yansıtmak için tipik bir durum :
'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output
Bu açıklama, anonim bir kullanıcıdan gelen bir düzenleme önerisine dayanmaktadır. Teşekkürler, her kimsen!
İşlem sırasına bağlı olarak, bu aşağıdaki sırayla çalışır:
,
Operatör değerleri dizisi test edilecek oluşturur.-ne
Bu durumda, boş - Belirtilen değerle aynı diziden tüm öğeler dışında operatör filtreler. Sonuç, Adım 1'de oluşturulan diziyle aynı sıradaki boş olmayan değerler dizisidir.[0]
filtrelenmiş dizinin ilk öğesini seçmek için kullanılır.Bunu basitleştirmek:
C # 'ın boş birleştirme operatörünün aksine, ilk adım bir dizi oluşturmak olduğundan, olası her ifade değerlendirilecektir.
function DidItRun($a) { Write-Host "It ran with $a"; return $a }
ve koşun ((DidItRun $null), (DidItRun 'alpha'), 1 -ne $null)[0]
.
,
bu kadar yüksek bir önceliğe sahip olduğunu her zaman unutuyorum . Bunun nasıl çalıştığı konusunda kafası karışan herkes ($null, 'alpha', 1 -ne $null)[0]
için aynı şey (($null, 'alpha', 1) -ne $null)[0]
. Aslında daha yüksek önceliğe sahip iki "tire" operatörü -split
ve -join
(ve tekli tire - yani. -4
Veya -'56'
) 'dir.
Bu, sorunun ilk yarısına verilen yarım yanıttır, yani eğer isterseniz çeyrek yanıttır, ancak kullanmak istediğiniz varsayılan değerin aslında tür için varsayılan değer olması koşuluyla boş birleştirme operatörüne çok daha basit bir alternatif vardır. :
string s = myval ?? "";
Powershell'de şu şekilde yazılabilir:
([string]myval)
Veya
int d = myval ?? 0;
Powershell'e çevirir:
([int]myval)
Bunlardan birincisini, var olmayabilecek ve varsa etrafında istenmeyen boşluklar olabilecek bir xml öğesini işlerken yararlı buldum:
$name = ([string]$row.td[0]).Trim()
Diziye çevrim, elemanın boş olmasına karşı koruma sağlar ve herhangi bir Trim()
arıza riskini önler .
([string]$null)
-> ""
"yararlı, ancak talihsiz bir yan etki" gibi görünüyor :(
$null, $null, 3 | Select -First 1
İadeler
3
Powershell Topluluk Uzantıları Modülünü yüklerseniz şunları kullanabilirsiniz:
?? Invoke-NullCoalescing için takma addır.
$s = ?? {$myval} {"New Value"}
?: Invoke-Ternary'nin takma adıdır.
$x = ?: {$myval -eq $null} {""} {$otherval}
Son olarak, PowerShell 7'de Null Coalescing atama operatörleri var !
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
Çoğu zaman, birleştirme kullanırken boş dizgeyi de boş olarak değerlendirmem gerektiğini görüyorum. Bunun için Zenexer'in basit boş birleştirme için birleştirme çözümünü kullanan bir işlev yazdım ve sonra sıfır veya boş denetim için Keith Hill'i kullandım ve işlevimin her ikisini de yapabilmesi için bunu bir bayrak olarak ekledim.
Bu işlevin avantajlarından biri, istisna atmadan tüm öğelerin boş (veya boş) olmasını da sağlamasıdır. Ayrıca, PowerShell'in dizi girişlerini işleme biçimi sayesinde rastgele birçok girdi değişkeni için de kullanılabilir.
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)
}
}
Bu, aşağıdaki test sonuçlarını üretir:
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
Test kodu:
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)
Alabileceğim en yakın şey: $Val = $MyVal |?? "Default Value"
Yukarıdakiler için boş birleştirme operatörünü şu şekilde uyguladım :
function NullCoalesc {
param (
[Parameter(ValueFromPipeline=$true)]$Value,
[Parameter(Position=0)]$Default
)
if ($Value) { $Value } else { $Default }
}
Set-Alias -Name "??" -Value NullCoalesc
Koşullu Üçlü operatör bir similary şekilde uygulanabilir.
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
Ve şu şekilde kullanılır: $Val = $MyVal |?: $MyVal "Default Value"