Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
PowerShell $null
genellikle basit gibi görünür, ancak çok fazla nüansları vardır. Haydi $null
'a yakından bakalım, böylece beklenmedik bir şekilde bir $null
değeriyle karşılaştığınızda ne olacağını bilirsiniz.
Uyarı
Bu makalenin özgün sürümü, @KevinMarquette tarafından yazılan blogda yer almıştır. PowerShell ekibi, bu içeriği bizimle paylaştığı için Kevin'e teşekkür ederiz. Lütfen PowerShellExplained.com'daki blogunu inceleyin.
NULL nedir?
NULL değerini bilinmeyen veya boş bir değer olarak düşünebilirsiniz. Bir değer veya nesne atayana kadar değişken NULL olur. Değer gerektiren ve değer NULL olduğunda hata oluşturan bazı komutlar olduğundan bu önemli olabilir.
PowerShell $null
$null
, PowerShell'de NULL değerini temsil etmek için kullanılan otomatik bir değişkendir. Bunu değişkenlere atayabilir, karşılaştırmalarda kullanabilir ve bir koleksiyonda NULL için yer tutucu olarak kullanabilirsiniz.
PowerShell, NULL değerine sahip bir nesne olarak kabul eder $null
. Bu, başka bir dilden geliyorsanız bekleyebileceğinizden farklıdır.
$null örnekleri
Başlatmadığınız bir değişken kullanmayı denediğinizde, değeri şeklindedir $null
. Bu, değerlerin kodunuz içine sızmasının $null
en yaygın yollarından biridir.
PS> $null -eq $undefinedVariable
True
Bir değişken adını yanlış yazdığınızda PowerShell bunu farklı bir değişken olarak görür ve değeri olur $null
.
$null
değerlerini bulmanın başka bir yolu, size hiçbir sonuç vermeyen diğer komutlardan gelmeleridir.
PS> function Get-Nothing {}
PS> $value = Get-Nothing
PS> $null -eq $value
True
$null'ın etkisi
$null
değerleri, kodunuzun nerede göründüğüne bağlı olarak farklı şekilde etkiler.
Dizelerde
Bir dizede kullanıyorsanız $null
, bu boş bir değerdir (veya boş dizedir).
PS> $value = $null
PS> Write-Output "'The value is $value'"
'The value is '
Bu, günlük iletilerinde kullanırken değişkenlerin çevresine köşeli ayraç yerleştirmeyi sevmemin nedenlerinden biridir. Değer dizenin sonundayken değişken değerlerinizin kenarlarını tanımlamak daha da önemlidir.
PS> $value = $null
PS> Write-Output "The value is [$value]"
The value is []
Bu, boş dizelerin ve $null
değerlerin kolayca tespit olmasını sağlar.
Sayısal bir denklemde
Sayısal denklemde bir $null
değer kullanıldığında, hata vermezlerse sonuçlarınız geçersiz olur. Bazen $null
, 0
olarak değerlendirilir ve diğer zamanlarda tüm sonucu $null
yapar.
Değerlerin sırasına bağlı olarak 0 veya $null
üreten bir çarpım örneği burada verilmiştir.
PS> $null * 5
PS> $null -eq ( $null * 5 )
True
PS> 5 * $null
0
PS> $null -eq ( 5 * $null )
False
Koleksiyon yerine
Koleksiyon, değerlere erişmek için dizin kullanmanıza olanak tanır. Aslında null
olan bir koleksiyonda dizin oluşturmaya çalışırsanız şu hatayı alırsınız: Cannot index into a null array
.
PS> $value = $null
PS> $value[10]
Cannot index into a null array.
At line:1 char:1
+ $value[10]
+ ~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
Bir koleksiyonunuz varsa ancak koleksiyonda olmayan bir öğeye erişmeye çalışırsanız, bir $null
sonuç alırsınız.
$array = @( 'one','two','three' )
$null -eq $array[100]
True
Nesne yerine
Belirtilen özelliğe sahip olmayan bir nesnenin özelliğine veya alt özelliğine erişmeye çalışırsanız, tanımlanmamış bir $null
değişken için yaptığınız gibi bir değer alırsınız. Değişkenin $null
bu durumda gerçek bir nesne olup olmadığı önemli değildir.
PS> $null -eq $undefined.Some.Fake.Property
True
PS> $date = Get-Date
PS> $null -eq $date.Some.Fake.Property
True
Null değere sahip bir ifadenin yöntemi
Bir $null
nesnede bir yöntemi çağırmak bir RuntimeException
oluşturur.
PS> $value = $null
PS> $value.ToString()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $value.ToString()
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
ifadeyi You cannot call a method on a null-valued expression
her gördüğümde, ilk baktığım şey, bir değişkende $null
kontrol etmeden bir fonksiyonu çağırdığım yerlerdir.
$null kontrolü
Örneklerimi kontrol $null
ederken her zaman sol tarafa yerleştirdiğim $null
fark etmiş olabilirsiniz. Bu, kasıtlı olarak yapılır ve PowerShell en iyi uygulaması olarak kabul edilir. Sağa yerleştirmenin size beklenen sonucu vermediği bazı senaryolar vardır.
Sonraki örneğe bakın ve sonuçları tahmin etmeye çalışın:
if ( $value -eq $null )
{
'The array is $null'
}
if ( $value -ne $null )
{
'The array is not $null'
}
Eğer $value
tanımlamazsam, ilk olan $true
ile değerlendirilir ve iletimiz The array is $null
olur. Buradaki tuzak, her ikisinin de $value
olmasına izin veren bir $false
yaratmanın mümkün olmasıdır.
$value = @( $null )
Bu durumda, $value
bir $null
içeren dizidir. dizideki -eq
her değeri denetler ve eşleşen değeri $null
döndürür. Bu, $false
olarak değerlendirilir.
-ne
eşleşmeyen $null
her şeyi döndürür ve bu durumda sonuç yoktur (Bu ayrıca $false
olarak değerlendirilir). İkisi de $true
değil, oysa biri öyle olmalı gibi görünüyor.
tr-TR: Hem ikisinin de $false
olarak değerlendirilmesini sağlayacak bir değer oluşturmak mümkündür, hem de her ikisinin $true
olarak değerlendirdiği bir değer oluşturmak mümkündür. Mathias Jessen (@IISResetMe) bu senaryoya göz atan iyi bir gönderiye sahiptir.
PSScriptAnalyzer ve VS Code
PSScriptAnalyzer modülü, adlı PSPossibleIncorrectComparisonWithNull
bu sorunu denetleen bir kurala sahiptir.
PS> Invoke-ScriptAnalyzer ./myscript.ps1
RuleName Message
-------- -------
PSPossibleIncorrectComparisonWithNull $null should be on the left side of equality comparisons.
VS Code da PSScriptAnalyser kurallarını kullandığından, bunu betiğinizde bir sorun olarak vurgular veya tanımlar.
Basit if kontrolü
kişilerin $null olmayan bir değeri denetlemesinin yaygın bir yolu, karşılaştırma olmadan basit if()
bir deyim kullanmaktır.
if ( $value )
{
Do-Something
}
Değer $null
ise, bu $false
olarak değerlendirilir. Bunu okumak kolaydır, ancak tam olarak beklediğiniz şeyi aradığından emin olun. Bu kod satırını şöyle okudum:
$value
bir değeri varsa.
Ama bütün hikaye bu değil. Bu satır aslında şunu söylüyor:
Eğer
$value
veya$null
veya0
veya$false
veya boş bir dize ya da boş bir dizi değilse.
Bu deyimin daha eksiksiz bir örneği aşağıda verilmiştir.
if ( $null -ne $value -and
$value -ne 0 -and
$value -ne '' -and
($value -isnot [array] -or $value.Length -ne 0) -and
$value -ne $false )
{
Do-Something
}
Temel bir if
kontrolü kullanmak, diğer değerlerin $false
olarak sayıldığını ve yalnızca bir değişkenin değeriyle sınırlı olmadığını hatırladığınız sürece tamamen kabul edilebilirdir.
Birkaç gün önce bazı kodları yeniden düzenlediğimde bu sorunla karşılaştım. Bunun gibi temel bir özellik denetimi vardı.
if ( $object.Property )
{
$object.Property = $value
}
Nesne özelliğine yalnızca varsa bir değer atamak istedim. Çoğu durumda, özgün nesnenin, $true
ifadesinde if
olarak değerlendirilecek bir değeri vardı. Ancak bazen değerin ayarlanmamasıyla ilgili bir sorunla karşılaştım. Kodda hata ayıklaması yaptım ve nesnenin özelliğine sahip olduğunu ancak boş bir dize değeri olduğunu tespit ettim. Bu, önceki mantıkla güncelleştirilmesini engelledi. Bu yüzden uygun bir $null
kontrol ekledim ve her şey işe yaradı.
if ( $null -ne $object.Property )
{
$object.Property = $value
}
Bunun gibi küçük hataları tespit etmek zor ve için değerleri $null
agresif bir şekilde kontrol etmemi sağlar.
$null. Saymak
Bir $null
değerinin bir özelliğine erişmeye çalışırsanız, bu özelliğin de $null
olduğunu görürsünüz.
Count
özelliği bu kuralın özel durumudur.
PS> $value = $null
PS> $value.Count
0
Bir $null
değeriniz olduğunda, Count
0
olur. Bu özel özellik PowerShell tarafından eklenir.
[PSCustomObject] Sayı
PowerShell'deki neredeyse tüm nesneler bu Count
özelliğe sahiptir. Windows PowerShell 5.1'deki önemli bir özel durumdur [pscustomobject]
(Bu, PowerShell 6.0'da düzeltilir). Bir Count
özelliği olmadığından, onu kullanmaya çalıştığınızda bir $null
değeri elde edersiniz. Burada belirtiyorum ki, Count
yerine $null
kontrolü kullanmaya çalışmayın.
Bu örneği Windows PowerShell 5.1 ve PowerShell 6.0'da çalıştırmak size farklı sonuçlar verir.
$value = [pscustomobject]@{Name='MyObject'}
if ( $value.Count -eq 1 )
{
"We have a value"
}
Numaralandırılabilir null
Diğerlerinden farklı davranan özel bir tür $null
vardır. Numaralandırılabilir null olarak adlandıracağım ama bu gerçekten bir System.Management.Automation.Internal.AutomationNull.
Bu numaralandırılabilir null, hiçbir şey döndüremeyen bir işlev veya betik bloğunun sonucu olarak elde ettiğiniz değerdir (geçersiz bir sonuç).
PS> function Get-Nothing {}
PS> $nothing = Get-Nothing
PS> $null -eq $nothing
True
ile $null
karşılaştırırsanız bir $null
değer alırsınız. Bir değerin gerekli olduğu bir değerlendirmede kullanıldığında, değer her zaman $null
şeklindedir. Ancak bir dizinin içine yerleştirirseniz, boş bir diziyle aynı şekilde değerlendirilir.
PS> $containEmpty = @( @() )
PS> $containNothing = @($nothing)
PS> $containNull = @($null)
PS> $containEmpty.Count
0
PS> $containNothing.Count
0
PS> $containNull.Count
1
Bir $null
değer içeren ve değeri Count
1
olan bir diziniz olabilir. Ancak dizi içine boş bir dizi yerleştirirseniz, öğe olarak sayılmaz. Sayı şeklindedir 0
.
Numaralandırılabilir null değerini bir koleksiyon gibi ele alırsanız boştur.
Kesin olarak yazılmamış bir işlevin parametresine numaralandırılabilir null değerini geçirirseniz, PowerShell varsayılan olarak bu numaralandırılabilir null değerini bir $null
değere dönüştürür. Bu, işlevin içinde değerin $null
türü yerine olarak ele alındığı anlamına gelir.
Boruhattı
Farkı en çok gördüğünüz yer, işlem hattını kullanırken olur.
$null
değerini yönlendirebilirsiniz, ancak numaralandırılabilir null değeri yönlendiremezsiniz.
PS> $null | ForEach-Object{ Write-Output 'NULL Value' }
'NULL Value'
PS> $nothing | ForEach-Object{ Write-Output 'No Value' }
Kodunuza bağlı olarak, mantığınızda $null
öğesini hesaba katmanız gerekir.
Ya önce $null
kontrol ediniz
- İşlem hattında null değerini filtreleme (
... | where {$null -ne $_} | ...
) - İşlem hattı fonksiyonunda onu hallet
foreach döngüsü
En sevdiğim özelliklerden foreach
biri, bir $null
koleksiyon üzerinde numaralandırma yapılmamasıdır.
foreach ( $node in $null )
{
#skipped
}
Bu, numaralandırmadan önce koleksiyonu denetlemem gerekme $null
neden olur. Bir dizi $null
değeriniz varsa, $node
yine $null
olabilir.
PowerShell foreach
3.0 ile bu şekilde çalışmaya başladı. Daha eski bir sürüm kullanıyorsanız bu durum geçerli değildir. Bu, 2.0 uyumluluğu için kodu geri taşıma sırasında dikkat edilmesi gereken önemli değişikliklerden biridir.
Değer türleri
Teknik olarak, yalnızca referans türleri $null
olabilir. Ancak PowerShell çok cömerttir ve değişkenlerin herhangi bir türde olmasını sağlar. Bir değer türünü katı şekilde belirtmeye karar verirseniz, $null
olamaz.
PowerShell, $null
birçok tür için varsayılan değere dönüştürür.
PS> [int]$number = $null
PS> $number
0
PS> [bool]$boolean = $null
PS> $boolean
False
PS> [string]$string = $null
PS> $string -eq ''
True
$null
'den geçerli bir dönüştürme yolu olmayan bazı türler vardır. Bu türler bir Cannot convert null to type
hata oluşturur.
PS> [datetime]$date = $null
Cannot convert null to type "System.DateTime".
At line:1 char:1
+ [datetime]$date = $null
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
İşlev parametreleri
İşlev parametrelerinde kesin olarak belirlenmiş değerler kullanmak çok yaygındır. Genellikle betiklerimizdeki diğer değişken türlerini tanımlamama eğiliminde olsak bile parametrelerimizin türlerini tanımlamayı öğreniriz. İşlevlerinizde zaten kesin olarak belirlenmiş bazı değişkenleriniz olabilir ve bunun farkında bile olmayabilirsiniz.
function Do-Something
{
param(
[string] $Value
)
}
Parametresinin türünü olarak string
ayarladığınız anda değer hiçbir zaman olamaz $null
. Bir değerin, kullanıcının bir değer sağıp sağlamadığını görmek için olup olmadığını denetlemek yaygın bir durumdur $null
.
if ( $null -ne $Value ){...}
$Value
hiçbir değer sağlanmayan boş bir dizedir ''
. Bunun yerine otomatik değişkeni $PSBoundParameters.Value
kullanın.
if ( $null -ne $PSBoundParameters.Value ){...}
$PSBoundParameters
yalnızca işlev çağrıldığında belirtilen parametreleri içerir.
Özelliği kontrol etmek için ContainsKey
yöntemini de kullanabilirsiniz.
if ( $PSBoundParameters.ContainsKey('Value') ){...}
IsNotNullOrEmpty
Değer bir dizeyse, değerin aynı anda boş bir dize olup olmadığını $null
denetlemek için statik dize işlevini kullanabilirsiniz.
if ( -not [string]::IsNullOrEmpty( $value ) ){...}
Değer türünün bir dize olması gerektiğini bildiğimde kendimi bunu sık sık kullanıyorum.
Ne zaman kontrol $null
Savunma senaryosunu ben yapıyorum. Bir işlevi çağırıp bir değişkene atadığım her zaman için $null
denetlenir.
$userList = Get-ADUser kevmar
if ($null -ne $userList){...}
if
veya foreach
kullanmayı try/catch
kullanmaya kıyasla tercih ederim. Yanlış anlamadım, hala çok kullanıyorum try/catch
. Ancak bir hata koşulu veya boş bir sonuç kümesi için test edebilirsem, özel durum işlememin gerçek özel durumlar için olmasını sağlayabilirim.
Bir nesnedeki bir değerin içine dizin oluşturmadan veya bir nesne üzerinde yöntem çağırmadan önce $null
kontrol etme eğilimindeyim. Bu iki eylem bir $null
nesne için başarısız olduğundan önce bunları doğrulamayı önemli buluyorum. Bu senaryoları bu gönderinin başlarında zaten ele aldım.
Sonuç senaryosu yok
Farklı işlevlerin ve komutların sonuç yok senaryolarını farklı işlediğini bilmeniz önemlidir. Birçok PowerShell komutu numaralandırılabilir null değerini ve hata akışında bir hata döndürür. Ya da diğerleri istisna oluşturur ya da size bir durum nesnesi verir. Kullandığınız komutların sonuç yok ve hata senaryolarıyla nasıl başa çıkdığını öğrenmek yine size kalmış.
$null başlat
Edindiğim bir alışkanlık, tüm değişkenlerimi kullanmadan önce başlatmak oldu. Bunu başka dillerde yapmanız gerekir. İşlevimin en üstünde veya bir foreach
döngüye girerken kullandığım tüm değerleri tanımlarım.
İşte size yakından bakmanızı istediğim bir senaryo. Daha önce kovalamak zorunda kaldığım bir hata örneği.
function Do-Something
{
foreach ( $node in 1..6 )
{
try
{
$result = Get-Something -Id $node
}
catch
{
Write-Verbose "[$result] not valid"
}
if ( $null -ne $result )
{
Update-Something $result
}
}
}
Beklenti, Get-Something
'nin bir sonuç veya numaralandırılabilir bir null döndürmesidir. Hata varsa, kaydediyoruz. Ardından işlemeden önce geçerli bir sonuç aldığımızdan emin olmak için kontrol ederiz.
Bu kodda gizlenen hata, Get-Something
bir hata fırlatıp $result
'e değer atayamaması durumudur. Göreve başlamadan önce başarısız olur, bu nedenle $null
, $result
değişkenine bile atanmaz.
$result
yine de diğer yinelemelerden önceki geçerli $result
değerleri içerir.
Update-Something
bu örnekte aynı nesne üzerinde birden çok kez yürütmek için.
Sorunu azaltmak için $result
'i $null
olarak ayarlıyorum ve bunu kullanmadan önce foreach
döngüsünün içine yerleştiriyorum.
foreach ( $node in 1..6 )
{
$result = $null
try
{
...
Kapsam sorunları
Bu, kapsam belirleme sorunlarının azaltılmasına da yardımcı olur. Bu örnekte, döngüde $result
'ye tekrar tekrar değer atanır. Ancak PowerShell işlevin dışındaki değişken değerlerin geçerli işlevin kapsamına taşmasına izin verdiğinden, bunları işlevinizin içinde başlatmak, bu şekilde ortaya konabilecek hataları azaltır.
İşlevinizdeki başlatılmamış bir değişken, üst kapsamdaki bir değere ayarlanmışsa değildir $null
.
Üst kapsam, işlevinizi çağıran ve aynı değişken adlarını kullanan başka bir işlev olabilir.
Aynı Do-something
örneği alıp döngüyü kaldırırsam, bu örneğe benzeyen bir şey elde ederim:
function Invoke-Something
{
$result = 'ParentScope'
Do-Something
}
function Do-Something
{
try
{
$result = Get-Something -Id $node
}
catch
{
Write-Verbose "[$result] not valid"
}
if ( $null -ne $result )
{
Update-Something $result
}
}
Get-Something
çağrısı bir özel durum oluşturursa, $null
denetimim $result
içinden Invoke-Something
öğesini bulur. İşlevinizin içindeki değerin başlatılması bu sorunu azaltır.
Değişkenleri adlandırmak zordur ve bir yazarın birden çok işlevde aynı değişken adlarını kullanması yaygındır. Her zaman kullandığımı $node
$result
$data
biliyorum. Bu nedenle, farklı kapsamlardaki değerlerin olmaması gereken yerlerde gösterilmesi çok kolay olacaktır.
Çıktıyı $null'a yönlendir.
Bu makalenin tamamı için değerlerden bahsediyorum $null
ancak çıktıyı 'a $null
yeniden yönlendirmeden bahsetmediysem konu tamamlanmamıştır. Bazı durumlarda, gizlemesini istediğiniz bilgilerin veya nesnelerin çıkışını veren komutlarınız vardır. Çıktıyı adresine $null
yönlendirmek bunu yapar.
Out-Null
Out-Null komutu, işlem hattı verilerini $null
öğesine yeniden yönlendirmenin yerleşik yoludur.
New-Item -Type Directory -Path $path | Out-Null
$null'a atama yap
Komutun sonuçlarını $null
'a atayarak Out-Null
kullanmanın aynı etkisini elde edebilirsiniz.
$null = New-Item -Type Directory -Path $path
$null
Sabit bir değer olduğundan, hiçbir zaman üzerine yazasınız. Kodumda görünme şeklini beğenmiyorum ama genellikle Out-Null
'den daha hızlı çalışır.
$null'a yeniden yönlendirme
Çıktıyı $null
'ye göndermek için yeniden yönlendirme işlecini de kullanabilirsiniz.
New-Item -Type Directory -Path $path > $null
Farklı akışlarda çıktı üreten komut satırı programlarıyla ilgileniyorsanız. Tüm çıkış akışlarını $null
şu şekilde yeniden yönlendirebilirsiniz:
git status *> $null
Özet
Bu konuda kapsamlı bir inceleme yaptım ve bu makalenin detaylı incelemelerimden daha parçalı olduğunu biliyorum. Bunun nedeni $null
, değerlerin PowerShell'de birçok farklı yerde açılabilir olması ve tüm nüansların onu bulduğunuz yere özel olmasıdır. Umarım karşılaşabileceğiniz daha belirsiz senaryoları daha iyi anlayıp $null
farkındalığınızla bu durumdan uzaklaşırsınız.
PowerShell