Diziler hakkında bilmek istediğiniz her şey


Diziler çoğu programlama dilinin temel bir dil özelliğidir. Kaçınılması zor olan değerler veya nesnelerin bir koleksiyonudurlar. Dizilere ve sundukları her şeye yakından bakalım.

Not

Bu makalenin orijinal versiyonu @KevinMarquette tarafından yazılan blogda yayınlandı. PowerShell ekibi bu içeriği bizimle paylaştığı için Kevin'e teşekkür ediyor. Lütfen PowerShellExplained.com adresindeki bloguna göz atın.

Dizi nedir?

PowerShell'in bunları kullandığı diğer yöntemlere geçmeden önce dizilerin ne olduğuna ve çoğu programlama dili tarafından nasıl kullanıldığına ilişkin temel bir teknik açıklamayla başlayacağım.

Dizi, birden fazla öğenin koleksiyonu olarak hizmet veren bir veri yapısıdır. Dizi üzerinde yineleme yapabilir veya bir dizin kullanarak tek tek öğelere erişebilirsiniz. Dizi, her değerin diğerinin hemen yanında depolandığı sıralı bir bellek yığını olarak oluşturulur.

İlerledikçe bu ayrıntıların her birine değineceğim.

Temel kullanım

Diziler PowerShell'in temel bir özelliği olduğundan, PowerShell'de onlarla çalışmak için basit bir sözdizimi vardır.

Bir dizi oluşturun

@() kullanılarak boş bir dizi oluşturulabilir

PS> $data = @()
PS> $data.count
0

Bir dizi oluşturabilir ve bunları yalnızca @() parantezlerine yerleştirerek değerlerle tohumlayabiliriz.

PS> $data = @('Zero','One','Two','Three')
PS> $data.count
4

PS> $data
Zero
One
Two
Three

Bu dizide 4 öğe var. $data değişkenini çağırdığımızda öğelerimizin listesini görüyoruz. Eğer bu bir dizi dizisiyse, o zaman dize başına bir satır elde ederiz.

Bir diziyi birden fazla satırda tanımlayabiliriz. Bu durumda virgül isteğe bağlıdır ve genellikle dışarıda bırakılır.

$data = @(
    'Zero'
    'One'
    'Two'
    'Three'
)

Dizilerimi bu şekilde birden çok satırda bildirmeyi tercih ederim. Birden fazla öğeniz olduğunda okumayı kolaylaştırmakla kalmaz, aynı zamanda kaynak kontrolünü kullanırken önceki sürümlerle karşılaştırmayı da kolaylaştırır.

Diğer sözdizimi

Genellikle @()'nin bir dizi oluşturmaya yönelik sözdizimi olduğu anlaşılır, ancak virgülle ayrılmış listeler çoğu zaman işe yarar.

$data = 'Zero','One','Two','Three'

Diziler oluşturmak için Yazma Çıkışı

Bahsetmeye değer harika küçük bir numara, konsolda hızlı bir şekilde dizeler oluşturmak için Write-Output'u kullanabilmenizdir.

$data = Write-Output Zero One Two Three

Bu kullanışlıdır çünkü parametre dizeleri kabul ettiğinde dizelerin etrafına tırnak işaretleri koymanız gerekmez. Bunu bir senaryoda asla yapmam ama konsolda adil bir oyun.

Öğelere erişme

Artık içinde öğeler bulunan bir diziniz olduğuna göre, bu öğelere erişip bunları güncellemek isteyebilirsiniz.

Telafi etmek

Tek tek öğelere erişmek için [] parantezlerini 0'dan başlayan uzaklık değeriyle kullanırız. Dizimizdeki ilk öğeyi bu şekilde elde ederiz:

PS> $data = 'Zero','One','Two','Three'
PS> $data[0]
Zero

Burada sıfır kullanmamızın nedeni, ilk öğenin listenin başında olması ve bu nedenle ona ulaşmak için 0 öğelik bir ofset kullanmamızdır. İkinci öğeye ulaşmak için ilk öğeyi atlamak amacıyla 1 ofsetini kullanmamız gerekir.

PS> $data[1]
One

Bu, son öğenin ofset 3'te olduğu anlamına gelir.

PS> $data[3]
Three

Dizin

Artık bu örnek için yaptığım değerleri neden seçtiğimi anlayabilirsiniz. Bunu bir ofset olarak tanıttım çünkü gerçekte olan budur, ancak bu ofset daha çok indeks olarak anılır. 0 ile başlayan bir dizin. Bu makalenin geri kalanında ofseti indeks olarak adlandıracağım.

Özel indeks püf noktaları

Çoğu dilde indeks olarak yalnızca tek bir sayı belirtebilirsiniz ve tek bir öğeyi geri alırsınız. PowerShell çok daha esnektir. Aynı anda birden fazla index kullanabilirsiniz. Bir dizin listesi sağlayarak birkaç öğe seçebiliriz.

PS> $data[0,2,3]
Zero
Two
Three

Öğeler, sağlanan dizinlerin sırasına göre döndürülür. Bir dizini kopyalarsanız, o öğeyi iki kere alırsınız.

PS> $data[3,0,3]
Three
Zero
Three

Yerleşik .. operatörüyle bir sayı dizisi belirtebiliriz.

PS> $data[1..3]
One
Two
Three

Bu tersten de çalışır.

PS> $data[3..1]
Three
Two
One

Sondan itibaren dengelemek için negatif dizin değerlerini kullanabilirsiniz. Yani listedeki son öğeye ihtiyacınız varsa -1 kullanabilirsiniz.

PS> $data[-1]
Three

Burada .. operatörüyle ilgili bir uyarıda bulunalım. 0..-1 ve -1..0 dizisi, 0,-1 ve -1,0 değerlerine göre değerlendirilir . $data[0..-1] dosyasını görmek ve bu ayrıntıyı unutursanız tüm öğeleri numaralandıracağını düşünmek kolaydır. $data[0..-1] size dizideki ilk ve son öğeyi vererek $data[0,-1] ile aynı değeri verir (ve diğer değerlerin hiçbiri). İşte daha büyük bir örnek:

PS> $a = 1,2,3,4,5,6,7,8
PS> $a[2..-1]
3
2
1
8

Bu şununla aynı:

PS> $a[2,1,0,-1]
3
2
1
8

sınırların dışında

Çoğu dilde, dizinin sonunu geçmiş bir öğenin dizinine erişmeye çalışırsanız, bir tür hata veya istisnayla karşılaşırsınız. PowerShell sessizce hiçbir şey döndürmez.

PS> $null -eq $data[9000]
True

Boş bir diziye indekslenemiyor

Değişkeniniz $null ise ve onu bir dizi gibi dizine eklemeye çalışırsanız, Cannot into index iletisiyle birlikte bir System.Management.Automation.RuntimeException istisnası alırsınız. boş bir dizi.

PS> $empty = $null
PS> $empty[0]
Error: Cannot index into a null array.

Bu nedenle, dizilerin içindeki öğelere erişmeye çalışmadan önce dizilerinizin $null olmadığından emin olun.

Saymak

Diziler ve diğer koleksiyonlar, dizide kaç öğe bulunduğunu söyleyen bir count özelliğine sahiptir.

PS> $data.count
4

PowerShell 3,0 çoğu nesneye count özelliği ekledi. tek bir nesneniz olabilir ve bu size 1 sayısını vermelidir.

PS> $date = Get-Date
PS> $date.count
1

$null bile, 0 döndürmesi dışında bir count özelliğine sahiptir.

PS> $null.count
0

Bu makalenin ilerleyen kısımlarında $null veya boş dizilerin kontrolünü ele aldığımda burada tekrar ele alacağım bazı tuzaklar var.

Tek tek hatalar

Diziler 0 indeksinden başladığı için yaygın bir programlama hatası yaratılır. Birer birer hatalar iki şekilde ortaya çıkabilir.

Birincisi, zihinsel olarak ikinci öğeyi istediğinizi düşünerek 2 dizinini kullanarak gerçekten üçüncü öğeyi elde etmektir. Veya dört öğeniz olduğunu ve son öğeyi istediğinizi düşünerek son öğeye erişmek için sayımı kullanırsınız.

$data[ $data.count ]

PowerShell bunu yapmanıza izin vermekten ve dizin 4'te tam olarak hangi öğenin bulunduğunu size vermekten son derece mutludur: $null. Yukarıda öğrendiğimiz $data.count - 1 veya -1 kullanıyor olmalısınız.

PS> $data[ $data.count - 1 ]
Three

Son öğeyi almak için -1 dizinini kullanabileceğiniz yer burasıdır.

PS> $data[ -1 ]
Three

Lee Dailey ayrıca maksimum indeks sayısını elde etmek için $data.GetUpperBound(0) komutunu kullanabileceğimizi de belirtti.

PS> $data.GetUpperBound(0)
3
PS> $data[ $data.GetUpperBound(0) ]
Three

İkinci en yaygın yol, listeyi tekrarlamak ve doğru zamanda durmamaktır. for döngüsünün kullanımından bahsettiğimizde buna tekrar değineceğim.

Öğeler güncelleniyor

Dizideki mevcut öğeleri güncellemek için aynı dizini kullanabiliriz. Bu bize bireysel öğeleri güncellemek için doğrudan erişim sağlar.

$data[2] = 'dos'
$data[3] = 'tres'

Son öğeyi geçmiş bir öğeyi güncellemeye çalışırsak Index was out of the array. hatası alırız.

PS> $data[4] = 'four'
Index was outside the bounds of the array.
At line:1 char:1
+ $data[4] = 'four'
+ ~~~~~~~~~~~~~
+ CategoryInfo          : OperationStopped: (:) [], IndexOutOfRangeException
+ FullyQualifiedErrorId : System.IndexOutOfRangeException

Bir dizinin nasıl büyütüleceğinden bahsettiğimde buna daha sonra tekrar değineceğim.

Yineleme

Bir noktada, listenin tamamını gezmeniz veya yinelemeniz ve dizideki her öğe için bazı eylemler gerçekleştirmeniz gerekebilir.

Boru hattı

Diziler ve PowerShell işlem hattı birbirleri içindir. Bu, bu değerleri işlemenin en basit yollarından biridir. Bir diziyi bir ardışık düzene aktardığınızda, dizi içindeki her öğe ayrı ayrı işlenir.

PS> $data = 'Zero','One','Two','Three'
PS> $data | ForEach-Object {"Item: [$PSItem]"}
Item: [Zero]
Item: [One]
Item: [Two]
Item: [Three]

Daha önce $PSItem'i görmediyseniz bunun $_ ile aynı şey olduğunu bilin. Her ikisini de kullanabilirsiniz çünkü her ikisi de işlem hattındaki geçerli nesneyi temsil eder.

ForEach döngüsü

ForEach döngüsü koleksiyonlarla iyi çalışır. Sözdizimini kullanma: foreach ( in )

foreach ( $node in $data )
{
    "Item: [$node]"
}

ForEach yöntemi

Bunu unutma eğilimindeyim ama basit işlemler için iyi çalışıyor. PowerShell, bir koleksiyonda .ForEach() öğesini çağırmanıza olanak tanır.

PS> $data.foreach({"Item [$PSItem]"})
Item [Zero]
Item [One]
Item [Two]
Item [Three]

.foreach(), bir komut dosyası bloğu olan bir parametreyi alır. Parantezleri bırakıp sadece komut dosyası bloğunu sağlayabilirsiniz.

$data.foreach{"Item [$PSItem]"}

Bu daha az bilinen bir sözdizimidir ancak aynı şekilde çalışır. Bu foreach yöntemi PowerShell 4.0'a eklenmiştir.

Döngü için

for döngüsü diğer dillerin çoğunda yoğun olarak kullanılır ancak bunu PowerShell'de pek göremezsiniz. Bunu gördüğünüzde, genellikle bir dizide yürüme bağlamındadır.

for ( $index = 0; $index -lt $data.count; $index++)
{
    "Item: [{0}]" -f $data[$index]
}

Yaptığımız ilk şey $index'i 0 olarak başlatmaktır. Daha sonra $index'in $data.count'tan küçük olması koşulunu ekliyoruz. Son olarak, her döngü yaptığımızda indeksi 1 artırmamız gerektiğini belirtiyoruz. Bu durumda $index++, $index=$index + 1'in kısaltmasıdır. Biçim operatörü (-f), çıktı dizesine $data[$index] değerini eklemek için kullanılır.

for döngüsünü her kullandığınızda, duruma özellikle dikkat edin. Burada $index -lt $data.count kullandım. Mantığınızda birer birer hata almak için koşulu biraz yanlış anlamak kolaydır. $index -le $data.count veya $index -lt ($data.count - 1) kullanmak biraz yanlıştır. Bu, sonucunuzun çok fazla veya çok az öğeyi işlemesine neden olur. Bu klasik birer birer hatadır.

Anahtar döngüsü

Bu gözden kaçması kolay bir şey. Bir switch ifadesine bir dizi sağlarsanız dizideki her öğeyi kontrol eder.

$data = 'Zero','One','Two','Three'
switch( $data )
{
    'One'
    {
        'Tock'
    }
    'Three'
    {
        'Tock'
    }
    Default
    {
        'Tick'
    }
}
Tick
Tock
Tick
Tock

Switch ifadesiyle yapabileceğimiz pek çok harika şey var. Buna adanmış başka bir makalem var.

  • Switch ifadesi hakkında bilmek istediğiniz her şey

Değerler güncelleniyor

Diziniz bir dize veya tamsayılar (değer türleri) koleksiyonu olduğunda, bazen dizideki değerleri döngü halindeyken güncellemek isteyebilirsiniz. Yukarıdaki döngülerin çoğu, döngüde değerin bir kopyasını tutan bir değişken kullanır. Bu değişkeni güncellerseniz dizideki orijinal değer güncellenmez.

Bu ifadenin istisnası for döngüsüdür. Bir dizide gezinmek ve içindeki değerleri güncellemek istiyorsanız, aradığınız şey for döngüsüdür.

for ( $index = 0; $index -lt $data.count; $index++ )
{
    $data[$index] = "Item: [{0}]" -f $data[$index]
}

Bu örnek, bir değeri dizine göre alır, birkaç değişiklik yapar ve ardından onu geri atamak için aynı dizini kullanır.

Nesne Dizileri

Şu ana kadar bir diziye yerleştirdiğimiz tek şey bir değer türüdür ancak diziler aynı zamanda nesneler de içerebilir.

$data = @(
    [pscustomobject]@{FirstName='Kevin';LastName='Marquette'}
    [pscustomobject]@{FirstName='John'; LastName='Doe'}
)

Çoğu cmdlet, nesne koleksiyonlarını bir değişkene atadığınızda diziler olarak döndürür.

$processList = Get-Process

Daha önce bahsettiğimiz temel özelliklerin tümü, işaret etmeye değer birkaç ayrıntıyla birlikte nesne dizileri için hala geçerlidir.

Özelliklere erişme

Değer türlerinde olduğu gibi bir koleksiyondaki tek bir öğeye erişmek için bir dizin kullanabiliriz.

PS> $data[0]

FirstName LastName
-----     ----
Kevin     Marquette

Özelliklere doğrudan erişebilir ve güncelleyebiliriz.

PS> $data[0].FirstName

Kevin

PS> $data[0].FirstName = 'Jay'
PS> $data[0]

FirstName LastName
-----     ----
Jay       Marquette

Dizi özellikleri

Normalde tüm özelliklere erişmek için listenin tamamını şu şekilde numaralandırmanız gerekir:

PS> $data | ForEach-Object {$_.LastName}

Marquette
Doe

Veya Select-Object -ExpandProperty cmdlet'ini kullanarak.

PS> $data | Select-Object -ExpandProperty LastName

Marquette
Doe

Ancak PowerShell bize doğrudan LastName talebinde bulunma olanağı sunuyor. PowerShell bizim için hepsini sıralar ve temiz bir liste döndürür.

PS> $data.LastName

Marquette
Doe

Numaralandırma hâlâ yapılıyor ancak arkasındaki karmaşıklığı göremiyoruz.

Nerede-Nesne filtreleme

Burası Nerede-Object'in devreye girdiği yerdir, böylece nesnenin özelliklerine göre diziden istediklerimizi filtreleyebilir ve seçebiliriz.

PS> $data | Where-Object {$_.FirstName -eq 'Kevin'}

FirstName LastName
-----     ----
Kevin     Marquette

Aradığımız FirstName'ı almak için aynı sorguyu yazabiliriz.

$data | Where FirstName -eq Kevin

Where()

Dizilerde, filtre için bir scriptblock belirlemenize olanak tanıyan bir Where() yöntemi bulunur.

$data.Where({$_.FirstName -eq 'Kevin'})

Bu özellik PowerShell 4.0'a eklendi.

Döngülerdeki nesneleri güncelleme

Değer türlerinde diziyi güncellemenin tek yolu for döngüsü kullanmaktır çünkü değeri değiştirecek dizini bilmemiz gerekir. Referans türleri oldukları için nesnelerle daha fazla seçeneğimiz var. İşte hızlı bir örnek:

foreach($person in $data)
{
    $person.FirstName = 'Kevin'
}

Bu döngü, $data dizisindeki her nesneyi yürütür. Nesneler referans türleri olduğundan, $person değişkeni dizideki nesnenin tam olarak aynısına başvurur. Dolayısıyla özelliklerinde yapılan güncellemeler orijinali günceller.

Hala nesnenin tamamını bu şekilde değiştiremezsiniz. $person değişkenine yeni bir nesne atamaya çalışırsanız, değişken referansını artık dizideki orijinal nesneye işaret etmeyen başka bir şeye güncellersiniz. Bu beklediğiniz gibi çalışmıyor:

foreach($person in $data)
{
    $person = [pscustomobject]@{
        FirstName='Kevin'
        LastName='Marquette'
    }
}

Operatörler

PowerShell'deki operatörler aynı zamanda diziler üzerinde de çalışır. Bazıları biraz farklı çalışıyor.

-join

-join operatörü en belirgin olanıdır o yüzden önce ona bakalım. -join operatörünü seviyorum ve sıklıkla kullanıyorum. Dizideki tüm öğeleri belirttiğiniz karakter veya dizeyle birleştirir.

PS> $data = @(1,2,3,4)
PS> $data -join '-'
1-2-3-4
PS> $data -join ','
1,2,3,4

-join operatörünün sevdiğim özelliklerinden biri de tekil öğeleri işlemesidir.

PS> 1 -join '-'
1

Bunu günlük kaydı ve ayrıntılı mesajların içinde kullanıyorum.

PS> $data = @(1,2,3,4)
PS> "Data is $($data -join ',')."
Data is 1,2,3,4.

-$array'e katıl

İşte Lee Dailey'nin bana işaret ettiği zekice bir numara. Her şeyi sınırlayıcı olmadan birleştirmek isterseniz, bunu yapmak yerine:

PS> $data = @(1,2,3,4)
PS> $data -join $null
1234

Öneksiz parametre olarak diziyle birlikte -join komutunu kullanabilirsiniz. Bahsettiğimi görmek için bu örneğe bir göz atın.

PS> $data = @(1,2,3,4)
PS> -join $data
1234

-değiştir ve -böl

-replace ve -split gibi diğer operatörler dizideki her öğe üzerinde yürütülür. Bunları şimdiye kadar bu şekilde kullandığımı söyleyemem ama işte bir örnek.

PS> $data = @('ATX-SQL-01','ATX-SQL-02','ATX-SQL-03')
PS> $data -replace 'ATX','LAX'
LAX-SQL-01
LAX-SQL-02
LAX-SQL-03

-contains

-contains operatörü, bir değer dizisini belirli bir değer içerip içermediğini kontrol etmenize olanak tanır.

PS> $data = @('red','green','blue')
PS> $data -contains 'green'
True

-in

Birkaç değerden biriyle eşleştiğini doğrulamak istediğiniz tek bir değeriniz olduğunda -in operatörünü kullanabilirsiniz. Değer operatörün solunda, dizi ise sağ tarafında olacaktır.

PS> $data = @('red','green','blue')
PS> 'green' -in $data
True

Liste büyükse bu pahalı olabilir. Birkaç değerden fazlasını kontrol ediyorsam sıklıkla normal ifade kalıbı kullanırım.

PS> $data = @('red','green','blue')
PS> $pattern = "^({0})$" -f ($data -join '|')
PS> $pattern
^(red|green|blue)$

PS> 'green' -match $pattern
True

-eq ve -ne

Eşitlik ve diziler karmaşıklaşabilir. Dizi sol tarafta olduğunda her öğe karşılaştırılır. True değerini döndürmek yerine eşleşen nesneyi döndürür.

PS> $data = @('red','green','blue')
PS> $data -eq 'green'
green

-ne operatörünü kullandığınızda değerimize eşit olmayan tüm değerleri elde ederiz.

PS> $data = @('red','green','blue')
PS> $data -ne 'green'
red
blue

Bunu bir if() ifadesinde kullandığınızda, döndürülen değer bir True değeridir. Hiçbir değer döndürülmezse bu bir False değeridir. Sonraki ifadelerin her ikisi de Doğru olarak değerlendirilir.

$data = @('red','green','blue')
if ( $data -eq 'green' )
{
    'Green was found'
}
if ( $data -ne 'green' )
{
    'And green was not found'
}

Biraz sonra $null testi hakkında konuştuğumuzda bu konuya tekrar değineceğim.

-match

-match operatörü koleksiyondaki her öğeyi eşleştirmeye çalışır.

PS> $servers = @(
    'LAX-SQL-01'
    'LAX-API-01'
    'ATX-SQL-01'
    'ATX-API-01'
)
PS> $servers -match 'SQL'
LAX-SQL-01
ATX-SQL-01

-match'i tek bir değerle kullandığınızda, özel bir $Matches değişkeni eşleşme bilgileriyle doldurulur. Bir dizi bu şekilde işlendiğinde durum böyle değildir.

Aynı yaklaşımı Select-String ile de uygulayabiliriz.

$servers | Select-String SQL

Regex'i kullanmanın birçok yolu adlı başka bir gönderide Select-String,-match ve $matches değişkenine daha yakından bakacağım.

$null veya boş

$null veya boş dizileri test etmek zor olabilir. Dizilerle ilgili yaygın tuzaklar şunlardır.

İlk bakışta bu ifade işe yarayacak gibi görünüyor.

if ( $array -eq $null)
{
    'Array is $null'
}

Ancak az önce -eq'in dizideki her bir öğeyi nasıl kontrol ettiğini inceledim. Yani tek bir $null değerine sahip birkaç öğeden oluşan bir dizimiz olabilir ve bu dizi $true olarak değerlendirilir.

$array = @('one',$null,'three')
if ( $array -eq $null)
{
    'I think Array is $null, but I would be wrong'
}

Bu nedenle $null karakterini operatörün sol tarafına yerleştirmek en iyi uygulamadır. Bu, bu senaryoyu sorun olmaktan çıkarır.

if ( $null -eq $array )
{
    'Array actually is $null'
}

$null dizisi boş bir diziyle aynı şey değildir. Bir diziniz olduğunu biliyorsanız, içindeki nesnelerin sayısını kontrol edin. Dizi $null ise sayı 0 olur.

if ( $array.count -gt 0 )
{
    "Array isn't empty"
}

Burada dikkat edilmesi gereken bir tuzak daha var. Tek bir nesneniz olsa bile, o nesne bir PSCustomObject olmadığı sürece count'u kullanabilirsiniz. Bu, PowerShell 6.1'de düzeltilen bir hatadır. Bu iyi bir haber ama pek çok kişi hâlâ 5.1 kullanıyor ve buna dikkat etmesi gerekiyor.

PS> $object = [PSCustomObject]@{Name='TestObject'}
PS> $object.count
$null

Hala PowerShell 5,1 kullanıyorsanız doğru bir sayı elde etmek için sayımı denetlemeden önce nesneyi bir diziye sarabilirsiniz.

if ( @($array).count -gt 0 )
{
    "Array isn't empty"
}

Tamamen güvenli oynamak için $null olup olmadığını kontrol edin, ardından sayımı kontrol edin.

if ( $null -ne $array -and @($array).count -gt 0 )
{
    "Array isn't empty"
}

Hepsi -eq

Geçenlerde Reddit'te birinin bir dizideki her değerin belirli bir değerle eşleştiğinin nasıl doğrulanacağını sorduğunu gördüm. Reddit kullanıcısı u/bis, yanlış değerleri kontrol eden ve ardından sonucu çeviren bu akıllı çözüme sahipti.

$results = Test-Something
if ( -not ( $results -ne 'Passed') )
{
    'All results a Passed'
}

Dizilere ekleme

Bu noktada bir diziye nasıl öğe ekleneceğini merak etmeye başlıyorsunuz. Hızlı cevap, yapamayacağınızdır. Bir dizi bellekte sabit bir boyuttur. Onu büyütmeniz veya ona tek bir öğe eklemeniz gerekiyorsa, yeni bir dizi oluşturmanız ve eski dizideki tüm değerleri kopyalamanız gerekir. Bu çok fazla iş gibi görünse de PowerShell yeni diziyi oluşturmanın karmaşıklığını gizliyor. PowerShell, diziler için toplama operatörünü (+) uygular.

Not

PowerShell çıkarma işlemi uygulamaz. Bir diziye esnek bir alternatif istiyorsanız genel bir List nesnesi kullanmanız gerekir.

Dizi ekleme

Yeni bir dizi oluşturmak için dizilerle birlikte toplama operatörünü kullanabiliriz. Yani bu iki dizi göz önüne alındığında:

$first = @(
    'Zero'
    'One'
)
$second = @(
    'Two'
    'Three'
)

Yeni bir dizi elde etmek için bunları bir araya getirebiliriz.

PS> $first + $second

Zero
One
Two
Three

Artı eşittir +=

Yerinde yeni bir dizi oluşturabilir ve ona şu şekilde bir öğe ekleyebiliriz:

$data = @(
    'Zero'
    'One'
    'Two'
    'Three'
)
$data += 'four'

+= komutunu her kullandığınızda kopyaladığınızı ve yeni bir dizi oluşturduğunuzu unutmayın. Bu, küçük veri kümeleri için bir sorun değildir ancak son derece zayıf bir şekilde ölçeklenir.

Boru hattı ataması

Herhangi bir işlem hattının sonuçlarını bir değişkene atayabilirsiniz. Birden fazla öğe içeriyorsa bu bir dizidir.

$array = 1..5 | ForEach-Object {
    "ATX-SQL-$PSItem"
}

Normalde işlem hattını kullanmayı düşündüğümüzde aklımıza tipik PowerShell tek satırlıkları gelir. foreach() ifadeleri ve diğer döngülerle işlem hattından yararlanabiliriz. Dolayısıyla, bir döngüdeki bir diziye öğe eklemek yerine, öğeleri ardışık düzene bırakabiliriz.

$array = foreach ( $node in (1..5))
{
    "ATX-SQL-$node"
}

Dizi Türleri

Varsayılan olarak PowerShell'de bir dizi [PSObject[]] türü olarak oluşturulur. Bu, herhangi bir nesne veya değer türünü içermesine olanak tanır. Bu işe yarar çünkü her şey PSObject türünden miras alınmıştır.

Kesinlikle yazılan diziler

Benzer bir sözdizimini kullanarak herhangi bir türden bir dizi oluşturabilirsiniz. Türü kesin olarak belirlenmiş bir dizi oluşturduğunuzda, yalnızca belirtilen türdeki değerleri veya nesneleri içerebilir.

PS> [int[]] $numbers = 1,2,3
PS> [int[]] $numbers2 = 'one','two','three'
ERROR: Cannot convert value "one" to type "System.Int32". Input string was not in a correct format."

PS> [string[]] $strings = 'one','two','three'

ArrayList

Bir diziye öğe eklemek en büyük sınırlamalarından biridir, ancak bu sorunu çözmek için başvurabileceğimiz birkaç koleksiyon daha vardır.

ArrayList, daha hızlı çalışacak bir diziye ihtiyaç duyduğumuzda genellikle aklımıza gelen ilk şeylerden biridir. İhtiyacımız olan her yerde bir nesne dizisi gibi davranır, ancak öğelerin eklenmesini hızlı bir şekilde gerçekleştirir.

Bir ArrayList'i nasıl oluşturacağımız ve ona öğeler ekleyeceğimiz aşağıda açıklanmıştır.

$myarray = [System.Collections.ArrayList]::new()
[void]$myArray.Add('Value')

Bu türü almak için .NET'i arıyoruz. Bu durumda, onu oluşturmak için varsayılan kurucuyu kullanıyoruz. Daha sonra ona bir öğe eklemek için Add yöntemini çağırıyoruz.

Satır başında [void] kullanmamın nedeni dönüş kodunu gizlemek. Bazı .NET çağrıları bunu yapar ve beklenmeyen çıktılar oluşturabilir.

Dizinizdeki tek veri dizelerse, StringBuilder kullanımına da bir göz atın. Neredeyse aynı şeydir ancak yalnızca dizelerle uğraşmaya yönelik bazı yöntemleri vardır. StringBuilder performans için özel olarak tasarlanmıştır.

İnsanların dizilerden ArrayList'e geçtiğini görmek yaygındır. Ancak bu, C#'ın genel desteğinin olmadığı bir zamandan geliyor. ArrayList, genel List[] desteği nedeniyle kullanımdan kaldırıldı

Genel Liste

Genel tür, C#'ta genelleştirilmiş bir sınıfı tanımlayan özel bir türdür ve kullanıcı, oluşturulduğunda kullandığı veri türlerini belirtir. Yani sayıların veya dizelerin bir listesini istiyorsanız, int veya string türlerinin listesini istediğinizi tanımlarsınız.

Dizeler için bir Listeyi nasıl oluşturacağınız aşağıda açıklanmıştır.

$mylist = [System.Collections.Generic.List[string]]::new()

Veya sayılar için bir liste.

$mylist = [System.Collections.Generic.List[int]]::new()

Önce nesneyi yaratmadan, mevcut bir diziyi şu şekilde bir listeye aktarabiliriz:

$mylist = [System.Collections.Generic.List[int]]@(1,2,3)

PowerShell 5 ve üzeri sürümlerde using namespace deyimiyle sözdizimini kısaltabiliriz. using ifadesinin betiğinizin ilk satırı olması gerekir. PowerShell, bir ad alanı bildirerek, bunlara başvururken onu veri türlerinin dışında bırakmanıza olanak tanır.

using namespace System.Collections.Generic
$myList = [List[int]]@(1,2,3)

Bu, Liste'yi çok daha kullanışlı hale getirir.

Kullanabileceğiniz benzer bir Ekle yöntemi var. ArrayList'ten farklı olarak Add yönteminde dönüş değeri yoktur, dolayısıyla onu geçersiz kılma zorunda değiliz.

$myList.Add(10)

Ve diğer diziler gibi öğelere hâlâ erişebiliyoruz.

PS> $myList[-1]
10

List[PSObject]

Herhangi bir türde bir listeniz olabilir, ancak nesnelerin türünü bilmediğinizde bunları içermek için [List[PSObject]] komutunu kullanabilirsiniz.

$list = [List[PSObject]]::new()

Remove()

Hem ArrayList hem de genel List[] öğelerin koleksiyondan kaldırılmasını destekler.

using namespace System.Collections.Generic
$myList = [List[string]]@('Zero','One','Two','Three')
[void]$myList.Remove("Two")
Zero
One
Three

Değer türleriyle çalışırken ilkini listeden kaldırır. Bu değeri kaldırmaya devam etmek için tekrar tekrar arayabilirsiniz. Referans türleriniz varsa kaldırılmasını istediğiniz nesneyi sağlamanız gerekir.

[list[System.Management.Automation.PSDriveInfo]]$drives = Get-PSDrive
$drives.remove($drives[2])
$delete = $drives[2]
$drives.remove($delete)

Remove yöntemi, öğeyi bulup koleksiyondan kaldırabildiyse true değerini döndürür.

Daha fazla koleksiyon

Kullanılabilecek başka birçok koleksiyon var ancak bunlar iyi genel dizi değişimleridir. Bu seçeneklerden daha fazlasını öğrenmek istiyorsanız Mark Kraus'un bir araya getirdiği bu Özet'e bir göz atın.

Diğer nüanslar

Artık tüm temel işlevleri ele aldığıma göre, bunu tamamlamadan önce bahsetmek istediğim birkaç şey daha var.

Önceden boyutlandırılmış diziler

Bir dizi oluşturulduktan sonra boyutunu değiştiremeyeceğinizden bahsetmiştim. Önceden belirlenmiş boyutta bir diziyi new($size) yapıcısıyla çağırarak oluşturabiliriz.

$data = [Object[]]::new(4)
$data.count
4

Dizileri çarpma

İlginç bir küçük numara, bir diziyi bir tamsayıyla çarpabilmenizdir.

PS> $data = @('red','green','blue')
PS> $data * 3
red
green
blue
red
green
blue
red
green
blue

0 ile başlat

Yaygın bir senaryo, tamamı sıfırlardan oluşan bir dizi oluşturmak istemenizdir. Yalnızca tamsayılara sahip olacaksanız, kesin olarak yazılmış bir tamsayı dizisinin tümü varsayılan olarak sıfırdır.

PS> [int[]]::new(4)
0
0
0
0

Bunu yapmak için çarpma hilesini de kullanabiliriz.

PS> $data = @(0) * 4
PS> $data
0
0
0
0

Çarpma numarasının güzel yanı, herhangi bir değeri kullanabilmenizdir. Dolayısıyla, varsayılan değeriniz olarak 255'i tercih ediyorsanız, bu bunu yapmanın iyi bir yolu olacaktır.

PS> $data = @(255) * 4
PS> $data
255
255
255
255

İç içe diziler

Bir dizinin içindeki diziye iç içe dizi denir. Bunları PowerShell'de pek kullanmıyorum ama diğer dillerde daha çok kullandım. Verileriniz ızgara benzeri bir desene sığdığında bir dizi dizi kullanmayı düşünün.

İki boyutlu bir dizi oluşturmanın iki yolunu burada bulabilirsiniz.

$data = @(@(1,2,3),@(4,5,6),@(7,8,9))

$data2 = @(
    @(1,2,3),
    @(4,5,6),
    @(7,8,9)
)

Bu örneklerde virgül çok önemlidir. Daha önce, virgülün isteğe bağlı olduğu birden fazla satırdaki normal dizi örneğini vermiştim. Çok boyutlu bir dizide durum böyle değil.

Artık iç içe geçmiş bir diziye sahip olduğumuz için indeks gösterimini kullanma şeklimiz biraz değişiyor. Yukarıdaki $data'yı kullanarak 3 değerine bu şekilde erişebiliriz.

PS> $outside = 0
PS> $inside = 2
PS> $data[$outside][$inside]
3

Her dizi iç içe geçme düzeyi için bir braket seti ekleyin. İlk parantez seti en dıştaki dizi içindir ve sonra oradan içeri girersiniz.

Yazma-Çıktı -Enumerate Yok

PowerShell dizilerin paketini açmayı veya numaralandırmayı sever. Bu, PowerShell'in işlem hattını kullanma biçiminin temel bir yönüdür ancak bunun olmasını istemediğiniz zamanlar da vardır.

Nesneleri genellikle onlar hakkında daha fazla bilgi edinmek için Get-Member'a yönlendiririm. Bir diziyi ona aktardığımda, paket açılıyor ve Get-Member gerçek diziyi değil dizinin üyelerini görüyor.

PS> $data = @('red','green','blue')
PS> $data | Get-Member
TypeName: System.String
...

Dizinin paketten çıkarılmasını önlemek için Write-Output -NoEnumerate komutunu kullanabilirsiniz.

PS> Write-Output -NoEnumerate $data | Get-Member
TypeName: System.Object[]
...

Daha çok hacklemeye yönelik ikinci bir yolum var (ve bunun gibi hacklerden kaçınmaya çalışıyorum). Diziyi aktarmadan önce dizinin önüne virgül koyabilirsiniz. Bu, $data'yı tek öğe olduğu başka bir diziye sarar, böylece dış dizinin paketini açtıktan sonra $data'yi paketi açılmış olarak geri alırız.

PS> ,$data | Get-Member
TypeName: System.Object[]
...

Bir dizi döndür

Dizilerin bu şekilde açılması, bir işlevden değerlerin çıktısını aldığınızda veya döndürdüğünüzde de gerçekleşir. Çıktıyı bir değişkene atarsanız yine de bir dizi elde edebilirsiniz, bu nedenle bu genellikle bir sorun değildir.

İşin püf noktası, yeni bir dizinizin olması. Eğer bu bir sorun olursa, bu sorunu çözmek için Write-Output -NoEnumerate $array veya return ,$array komutunu kullanabilirsiniz.

Başka bir şey?

Bunların dikkate alınması gereken çok şey olduğunu biliyorum. Umudum, bu makaleyi her okuduğunuzda bir şeyler öğrenmeniz ve bunun sizin için uzun süre iyi bir referans olarak ortaya çıkmasıdır. Bunu yararlı bulduysanız, lütfen bundan değer kazanabileceğini düşündüğünüz diğer kişilerle paylaşın.

Buradan hashtable'lar hakkında yazdığım benzer bir yazıya göz atmanızı tavsiye ederim.

İlgili makaleler