Aracılığıyla paylaş


Diziler hakkında bilmek istediğiniz her şey

Diziler , çoğu programlama dilinin temel dil özelliğidir. Bunlar, kaçınılması zor olan değerlerden veya nesnelerden oluşan bir koleksiyon. Dizilere ve sundukları her şeye yakından bakalım.

Not

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.

Dizi nedir?

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

Dizi, birden çok öğeden oluşan bir koleksiyon 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 hemen yanında depolandığı sıralı bellek öbekleri olarak oluşturulur.

Bu ayrıntıların her birine değineceğim.

Temel kullanım

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

Dizi oluşturma

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

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

Bir dizi oluşturabilir ve bunları yalnızca parantez içine 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. değişkenini $data çağırdığımızda öğelerimizin listesini görürüz. Bu bir dize dizisiyse, dize başına bir satır elde ederiz.

Bir diziyi birden çok satırda bildirebiliriz. Virgül bu durumda isteğe bağlıdır ve genel olarak dışarıda bırakılır.

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

Dizilerimi bunun gibi birden çok satırda bildirmeyi tercih ederim. Yalnızca birden çok öğeniz olduğunda okunması kolaylaşır, aynı zamanda kaynak denetimi kullanılırken önceki sürümlerle karşılaştırmayı da kolaylaştırır.

Diğer söz dizimi

Genellikle dizi oluşturmak için söz dizimi olduğu @() anlaşılır, ancak virgülle ayrılmış listeler çoğu zaman çalışır.

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

Dizi oluşturmak için Write-Output

Bahsetmeye değer küçük bir püf noktası, konsolda hızlı bir şekilde dize oluşturmak için kullanabileceğinizdir Write-Output .

$data = Write-Output Zero One Two Three

Parametre dizeleri kabul ettiğinde dizelerin etrafına tırnak işareti koymanız gerekmediğinden bu kullanışlıdır. Bunu asla bir betikte yapmam ama konsolda adil bir oyun.

Öğelere erişme

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

Atlanacak sayı

Tek tek öğelere erişmek için köşeli ayraçları [] 0'dan başlayan bir 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 kullanma nedenimiz, ilk öğenin listenin başında olmasıdır, bu nedenle bu öğeye ulaşmak için 0 öğeden oluşan bir uzaklık kullanırız. İkinci öğeye ulaşmak için ilk öğeyi atlamak için 1 uzaklığını kullanmamız gerekir.

PS> $data[1]
One

Bu, son öğenin 3 uzaklığında olduğu anlamına gelir.

PS> $data[3]
Three

Dizin oluşturma

Şimdi bu örnek için yaptığım değerleri neden seçtiğimi görebilirsiniz. Bunu bir uzaklık olarak tanıttım çünkü bu aslında budur, ancak bu uzaklık daha yaygın olarak bir dizin olarak adlandırılır. adresinden 0başlayan bir dizin. Bu makalenin geri kalanında uzaklığı bir dizin olarak adlandıracağım.

Özel dizin püf noktaları

Çoğu dilde, dizin olarak yalnızca tek bir sayı belirtebilirsiniz ve tek bir öğeyi geri alırsınız. PowerShell çok daha esnektir. Aynı anda birden çok dizin kullanabilirsiniz. Dizinlerin listesini 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 yinelerseniz, bu öğeyi her iki kez de alırsınız.

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

Yerleşik .. işleçle bir sayı dizisi belirtebiliriz.

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

Bu da tersten çalışır.

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

Sonundan uzaklık için negatif dizin değerleri kullanabilirsiniz. Bu nedenle listedeki son öğeye ihtiyacınız varsa kullanabilirsiniz -1.

PS> $data[-1]
Three

Burada işleçle ilgili .. tek bir uyarı. ve 0..-1-1..0 değerlerine 0,-1 göre değerlendirilir.-1,0 Bu ayrıntıyı unutursanız tüm öğeleri numaralandıracağını düşünmek ve görmek $data[0..-1] kolaydır. $data[0..-1] size dizideki ilk ve son öğeyi (ve diğer değerlerden hiçbirini vermeyerek) ile aynı $data[0,-1] değeri verir. Aşağıda daha büyük bir örnek verilmiştir:

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

Bu, aşağıdakiyle aynıdır:

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 özel durumla karşılaşırsınız. PowerShell sessizce hiçbir şey döndürmez.

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

Null dizide dizin oluşturulamıyor

Değişkeniniz ise $null ve bunu bir dizi gibi dizine almaya çalışırsanız, iletisiyle Cannot index into a null arraybir System.Management.Automation.RuntimeException özel durum alırsınız.

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

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

Sayı

Diziler ve diğer koleksiyonlar, dizide kaç öğe olduğunu belirten bir count özelliğine sahiptir.

PS> $data.count
4

PowerShell 3.0 çoğu nesneye bir count özelliği ekledi. tek bir nesneniz olabilir ve size bir sayı 1vermelidir.

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

Döndürmesi dışında 0count özelliği bile $null vardır.

PS> $null.count
0

Burada, bu makalenin devamında dizileri denetlemeyi veya boş dizileri ele $null alacağımda tekrar ziyaret edeceğim bazı tuzaklar var.

Tek tek hatalar

Diziler dizin 0'da başladığından yaygın bir programlama hatası oluşturulur. Tek tek hatalar iki şekilde ortaya çıkarılabilir.

Birincisi, zihinsel olarak ikinci öğeyi istediğinizi düşünmek ve üçüncü öğeyi gerçekten almak için 2 bir dizin kullanmaktır. Ya da dört öğeniz olduğunu ve son öğeyi istediğinizi düşünerek, son öğeye erişmek için sayıyı kullanırsınız.

$data[ $data.count ]

PowerShell, bunu yapmanıza izin vermek ve dizin 4'te tam olarak hangi öğenin mevcut olduğunu size vermek için son derece mutlu: $null. Yukarıda öğrendiğimiz veya -1 kullanıyor olmanız $data.count - 1 gerekir.

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

Son öğeyi -1 almak için dizini burada kullanabilirsiniz.

PS> $data[ -1 ]
Three

Lee Dailey ayrıca maksimum dizin numarasını almak için kullanabileceğimizi $data.GetUpperBound(0) de bana işaret etti.

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

İkinci en yaygın yol, listenin yinelenip doğru zamanda durdurulmamasıdır. Döngünün kullanılmasından for söz ettiğimizde bunu tekrar ziyaret edeceğim.

Öğeleri güncelleştirme

Dizideki mevcut öğeleri güncelleştirmek için aynı dizini kullanabiliriz. Bu, tek tek öğeleri güncelleştirmek için doğrudan erişim sağlar.

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

Son öğeyi geçmiş bir öğeyi güncelleştirmeye çalışırsak bir Index was outside the bounds of the array. hatayla karşılaşı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

Bunu daha sonra bir diziyi nasıl daha büyük hale getireceğimden bahsederken tekrar ziyaret edeceğim.

Yineleme

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

İşlem Hattı

Diziler ve PowerShell işlem hattı birbirine yöneliktir. Bu, bu değerler üzerinde işlem yapmanın en basit yollarından biridir. Bir diziyi bir işlem hattına geçirdiğinizde, 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 görmediyseniz $PSItem , bunun ile $_aynı şey olduğunu bilmeniz gerekir. her ikisi de işlem hattındaki geçerli nesneyi temsil ettiğinden birini kullanabilirsiniz.

ForEach döngüsü

Döngü, ForEach koleksiyonlarla iyi çalışır. Söz dizimini kullanma: foreach ( <variable> in <collection> )

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

ForEach yöntemi

Bunu unutma eğilimindeyim ama basit operasyonlar için iyi çalışıyor. PowerShell, bir koleksiyonda arama .ForEach() yapmanızı sağlar.

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

, .foreach() betik bloğu olan bir parametre alır. Parantezleri bırakabilir ve yalnızca betik bloğunu sağlayabilirsiniz.

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

Bu daha az bilinen bir söz dizimidir, ancak aynı şekilde çalışır. Bu foreach yöntem PowerShell 4.0'a eklendi.

for döngüsü

Döngü for diğer dillerin çoğunda yoğun olarak kullanılır, ancak bunu PowerShell'de çok fazla görmezsiniz. Gördüğünüzde, genellikle bir diziyi yürüme bağlamında olur.

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

yaptığımız ilk şey için bir $index0başlatmaktır. Ardından değerinden $index küçük $data.countolması gereken koşulu ekleyeceğiz. Son olarak, her döngü yaptığımızda dizini ile 1artırmamız gerektiğini belirtiriz. Bu durumda $index++ , için $index = $index + 1kısadır. biçim işleci (-f), çıkış dizesine değerini $data[$index] eklemek için kullanılır.

Döngü kullandığınızda for koşula özellikle dikkat edin. Burada kullandım $index -lt $data.count . Mantığınızda bire bir hata almak için durumu biraz yanlış almak kolaydır. veya $index -lt ($data.count - 1) kullanmak $index -le $data.count çok az yanlıştır. Bu, sonucunuzun çok fazla veya çok az öğe işlemesine neden olur. Bu, klasik bire bir hatadır.

Geçiş döngüsü

Bu göz ardı etmek kolay bir şey. Switch deyimine bir dizi sağlarsanız, dizideki her öğeyi denetler.

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

Switch deyimiyle yapabileceğimiz birçok harika şey vardır. Buna adanmış başka bir makalem daha var.

Değerler güncelleştiriliyor

Diziniz dize veya tamsayılardan (değer türleri) oluşan bir koleksiyon olduğunda, bazen dizideki değerleri döngüye alırken güncelleştirmek 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üncelleştirirseniz, dizideki özgün değer güncelleştirilmez.

Bu deyimin özel durumu döngüdür for . Bir dizide gezinmek ve içindeki değerleri güncelleştirmek istiyorsanız, for aradığınız döngüdür.

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

Bu örnek dizine göre bir değer alır, birkaç değişiklik yapar ve ardından aynı dizini kullanarak yeniden atar.

Nesne Dizileri

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

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

Birçok cmdlet, nesneleri bir değişkene atadığınızda koleksiyonları dizi olarak döndürür.

$processList = Get-Process

Daha önce bahsettiğimiz temel özelliklerin tümü, işaret etmeye değer birkaç ayrıntı içeren 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 özellikleri güncelleştirebiliriz.

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ı şöyle listelemeniz gerekir:

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

Marquette
Doe

Veya cmdlet'ini Select-Object -ExpandProperty kullanarak.

PS> $data | Select-Object -ExpandProperty LastName

Marquette
Doe

Ancak PowerShell bize doğrudan istekte LastName bulunma olanağı sunar. PowerShell hepsini bizim için numaralandırır ve temiz bir liste döndürür.

PS> $data.LastName

Marquette
Doe

Numaralandırma yine de gerçekleşir, ancak bunun ardındaki karmaşıklığı görmüyoruz.

Where-Object filtreleme

Burada Where-Object , nesnenin özelliklerine göre diziden istediklerimizi filtreleyebilir ve seçebiliriz.

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

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

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

$data | Where FirstName -eq Kevin

Where()

Diziler, filtre için bir belirtmenize olanak tanıyan bir Where()scriptblock yönteme sahiptir.

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

Bu özellik PowerShell 4.0'a eklendi.

Döngülerdeki nesneleri güncelleştirme

Değer türleriyle, diziyi güncelleştirmenin tek yolu for döngüsü kullanmaktır çünkü değeri değiştirmek için dizini bilmemiz gerekir. Nesneler başvuru türleri olduğundan, nesnelerle ilgili daha fazla seçenek vardır. Aşağıda hızlı bir örnek verilmiştir:

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

Bu döngü dizideki $data her nesneyi yürüyor. Nesneler başvuru türleri olduğundan, $person değişken dizideki tam olarak aynı nesneye başvurur. Bu nedenle, özelliklerindeki güncelleştirmeler özgün güncelleştirmeyi güncelleştirir.

Yine de nesnenin tamamını bu şekilde değiştiremezsiniz. Değişkene yeni bir nesne atamaya $person çalışırsanız, değişken başvuruyu artık dizideki özgün nesneye işaret etmeyen başka bir şeye güncelleştireceksiniz. Bu, beklediğiniz gibi çalışmaz:

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

İşleçler

PowerShell'deki işleçler diziler üzerinde de çalışır. Bazıları biraz farklı çalışır.

-birleştirmek

İşleç -join en belirgin olanıdır, bu nedenle önce buna bakalım. Operatörü seviyorum -join ve sık sık 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

Operatörle ilgili sevdiğim özelliklerden -join biri, tek öğeleri işlemesi.

PS> 1 -join '-'
1

Bunu günlüğe kaydetme ve ayrıntılı iletilerin içinde kullanıyorum.

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

-join $array

İşte Lee Dailey'in bana işaret yaptığı akıllı bir numara. Bunu yapmak yerine her şeyi sınırlayıcı olmadan birleştirmek isterseniz:

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

Ön ek olmadan parametresi olarak dizi ile kullanabilirsiniz -join . Bahsettiğimi görmek için bu örneğe göz atın.

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

-replace ve -split

Diğer işleçler dizideki her öğeyi beğenir -replace ve -split yürütür. Bunları daha önce bu şekilde kullandığımı söyleyemem ama bir örnek aşağıda verilmiştir.

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

-Içerir

işleci, -contains belirli bir değer içerip içermediğini görmek için bir değer dizisini denetlemenize olanak tanır.

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

-içinde

Doğrulamak istediğiniz tek bir değer birden çok değerden biriyle eşleştiğinde işlecini -in kullanabilirsiniz. Değer solda, dizi ise işlecin sağ tarafında olacaktır.

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

Liste büyükse bu işlem pahalıya gelebilir. Birkaç değerden fazlasını denetlediğim zaman genellikle bir regex deseni 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şık olabilir. Dizi sol tarafta olduğunda, her öğe karşılaştırılır. döndürmek Trueyerine, eşleşen nesneyi döndürür.

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

işlecini -ne 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() deyimde kullandığınızda, döndürülen bir değer bir True değerdir. Değer döndürülmezse, bu bir False değerdir. Bu sonraki deyimlerin her ikisi de olarak Truedeğerlendirilir.

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

Test hakkında $nullkonuştuğumuzda bunu tekrar ziyaret edeceğim.

-maç

-match işleci 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

Tek bir değerle kullandığınızda -match , özel bir değişken $Matches eşleşme bilgileriyle doldurulur. Bir dizi bu şekilde işlendiğinde bu durum geçerli değildir.

ile Select-Stringde aynı yaklaşımı benimsebiliriz.

$servers | Select-String SQL

regex kullanmanın birçok yolu adlı başka bir gönderideki değişkenine ve $matches değişkenine daha yakından bakıyorumSelect-String-match.

$null veya boş

Veya boş diziler için $null test zor olabilir. Dizilerle ilgili yaygın tuzaklar aşağıdadır.

Bir bakışta, bu deyim işe yaraması gerektiği gibi görünür.

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

Ama dizideki her öğeyi nasıl -eq denetleyebilirim diye biraz araştırdım. Bu nedenle, tek bir $null değerine sahip birkaç öğeden oluşan bir dizimiz olabilir ve bu değer şu şekilde değerlendirilir: $true

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

Bu nedenle, işlecin sol tarafına yerleştirmek $null en iyi yöntemdir. Bu, bu senaryoya sorun oluşturmaz.

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

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

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

Burada dikkate alınacak bir tuzak daha var. Tek bir nesneniz olsa bile, bu nesne bir PSCustomObjectolmadığı sürece öğesini kullanabilirsinizcount. Bu, PowerShell 6.1'de düzelten bir hatadır. Bu iyi bir haber, ama birçok insan hala 5.1'de ve buna dikkat etmek zorunda.

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ıyı denetlemeden önce nesneyi bir dizide sarmalayabilirsiniz.

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

Güvenli bir şekilde yürütmek için $nullöğesini denetleyin ve ardından sayıyı denetleyin.

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

Tümü -eq

Yakın zamanda Reddit'te bir dizideki her değerin belirli bir değerle eşleşeceğini nasıl doğrulayacaklarını soran birini gördüm. Reddit kullanıcısının u/bis yanlış değerleri denetlediği ve ardından sonucu çeviren akıllı bir çözümü vardı.

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

Dizilere ekleme

Bu noktada, diziye nasıl öğe ekleneceğini merak etmeye başlıyorsunuz. Hızlı yanıt, bunu yapamazsınız. Dizi, bellekte sabit bir boyuta sahiptir. Büyütmeniz veya tek bir öğe eklemeniz gerekiyorsa, yeni bir dizi oluşturmanız ve eski dizideki tüm değerleri kopyalamanız gerekir. Bununla birlikte, PowerShell yeni dizi oluşturmanın karmaşıklığını gizler. PowerShell diziler için toplama işlecini (+) uygular.

Not

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

Dizi ekleme

Yeni bir dizi oluşturmak için toplama işlecini dizilerle birlikte kullanabiliriz. Bu nedenle şu iki dizi göz önünde bulundurulduğunda:

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

Yeni bir dizi almak için bunları bir araya ekleyebiliriz.

PS> $first + $second

Zero
One
Two
Three

Artı eşittir +=

Yerinde yeni bir dizi oluşturabilir ve buna aşağıdaki gibi bir öğe ekleyebiliriz:

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

Bunu her kullandığınızda += yeni bir dizi çoğaltıp oluşturduğunuzu unutmayın. Bu küçük veri kümeleri için bir sorun değildir, ancak son derece kötü ölçeklendirilir.

İşlem hattı ataması

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

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

Normalde işlem hattını kullanmayı düşündüğümüzde, tipik PowerShell tek satırlılarını düşünüriz. deyimleri ve diğer döngülerle foreach() işlem hattından yararlanabiliriz. Bu nedenle döngüdeki bir diziye öğe eklemek yerine öğeleri işlem hattına bırakabiliriz.

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

Dizi Türleri

Varsayılan olarak, PowerShell'de bir dizi tür olarak [PSObject[]] oluşturulur. Bu, herhangi bir tür nesne veya değer içermesine olanak tanır. Her şey türünden PSObject devralındığından bu işe yarar.

Kesin türemiş diziler

Benzer bir söz dizimi kullanarak herhangi bir türde dizi oluşturabilirsiniz. Kesin olarak yazılan 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 kullanabileceğimiz birkaç koleksiyon daha vardır.

ArrayList genellikle daha hızlı çalışabilen bir diziye ihtiyacımız olduğunda düşündüğümüz ilk şeylerden biridir. İhtiyacımız olan her yerde bir nesne dizisi gibi davranır, ancak öğeleri hızla ekler.

Oluşturma ve öğe ekleme işlemi aşağıda ArrayList açıklanıyor.

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

Bu türü almak için .NET'e çağrı yapıyoruz. Bu durumda, oluşturmak için varsayılan oluşturucuyu kullanıyoruz. Ardından bir öğe eklemek için yöntemini çağırırız Add .

Satırın başında kullanmamın [void] nedeni, dönüş kodunun gösterilmemesidir. Bazı .NET çağrıları bunu yapar ve beklenmeyen çıkışlar oluşturabilir.

Dizinizdeki tek veri dizelerse StringBuilder'ı kullanma konusuna da göz atın. Neredeyse aynı şeydir, ancak yalnızca dizelerle ilgilenmek için bazı yöntemleri vardır. StringBuilder, performans için özel olarak tasarlanmıştır.

İnsanların dizilerden geçişlerini ArrayList görmek yaygın bir durumdur. Ancak C# dilinin genel destek almadığı bir dönemden gelir. ArrayList genel desteğinde kullanım dışı bırakıldıList[]

Genel Liste

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

Dizeler için liste oluşturma burada anlatılır.

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

Ya da sayılar için bir liste.

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

Var olan bir diziyi, önce nesnesini oluşturmadan aşağıdaki gibi bir listeye dönüştürebiliriz:

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

Söz dizimini PowerShell 5 ve daha yeni sürümlerde deyimiyle using namespace kısaltabiliriz. deyiminin using betiğinizin ilk satırı olması gerekir. PowerShell, bir ad alanı bildirerek, başvuruda bulunurken bu ad alanını veri türlerinden uzak bırakmanıza olanak tanır.

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

Bu, çok List daha kullanılabilir hale getirir.

Kullanabileceğiniz benzer Add bir yönteminiz vardır. ArrayList'in aksine, yönteminde Add dönüş değeri yoktur, bu nedenle buna gerek void yoktur.

$myList.Add(10)

Ayrıca diğer diziler gibi öğelere de erişebiliriz.

PS> $myList[-1]
10

List[PSObject]

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

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

Remove()

ArrayList ve genel List[] her ikisi de koleksiyondan öğe kaldırmayı 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 bunu tekrar tekrar çağırabilirsiniz. Başvuru 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 döndürür true .

Diğer koleksiyonlar

Kullanılabilecek başka birçok koleksiyon vardır, ancak bunlar iyi genel dizi değiştirmeleridir. Bu seçeneklerden daha fazlasını öğrenmek istiyorsanız Mark Kraus'un bir araya topladığınız bu Gist'e göz atın.

Diğer nüanslar

Şimdi tüm önemli işlevleri ele aldım, bunu tamamlamadan önce bahsetmek istediğim birkaç şey daha var.

Önceden boyutlandırılmış diziler

Bir dizi oluşturulduktan sonra boyutunu değiştirememenizi söyledim. Oluşturucuyla new($size) çağırarak önceden belirlenmiş boyutta bir dizi oluşturabiliriz.

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

Dizileri çarpma

İlginç bir küçük püf noktası, bir diziyi bir tamsayı ile çarpmanızdır.

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

0 ile başlatma

Yaygın bir senaryo, tüm sıfırlarla bir dizi oluşturmak istemenizdir. Yalnızca tamsayılara sahip olacaksanız, kesin olarak belirlenmiş bir tamsayı dizisi varsayılan olarak tüm sıfırları kullanı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 hilesinin güzel yanı, herhangi bir değeri kullanabilmenizdir. Bu nedenle, varsayılan değeriniz olmasını tercih 255 ederseniz, bunu yapmak için iyi bir yol olabilir.

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

İç içe diziler

Dizi içindeki bir dizi iç içe dizi olarak adlandırılır. PowerShell'de bu kadar çok kullanmıyorum ama bunları diğer dillerde daha fazla kullandım. Verileriniz desen gibi bir kılavuza sığdığında dizi dizileri kullanmayı göz önünde bulundurun.

İki boyutlu bir dizi oluşturmanın iki yolu aşağıdadır.

$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. Virgül isteğe bağlı olan birden çok satırda normal bir dizi örneği vermiştim. Çok boyutlu bir dizide böyle bir durum söz konusu değildir.

Dizin gösterimini kullanma şeklimiz, iç içe dizimiz olduğu için biraz değişiyor. Yukarıdakini $data kullanarak 3 değerine bu şekilde erişebiliriz.

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

Dizi iç içe yerleştirmenin her düzeyi için bir köşeli ayraç kümesi ekleyin. İlk köşeli ayraç kümesi en dıştaki diziye yöneliktir ve ardından oradan içeri doğru çalışırsınız.

Write-Output -NoEnumerate

PowerShell dizileri açmak veya numaralandırmak ister. Bu, PowerShell'in işlem hattını kullanma şeklinin temel bir yönüdür, ancak bazen bunun olmasını istemezsiniz.

Nesneler hakkında daha fazla bilgi edinmek için Get-Member genellikle nesneleri yöneltiyorum. Bir diziyi ona yönelttiğim zaman, bu dizi eşlenmemiş hale gelir ve Get-Member gerçek diziyi değil dizinin üyelerini görür.

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

Dizinin bu şekilde çözülmesini önlemek için kullanabilirsiniz Write-Output -NoEnumerate.

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

Daha çok bir hack olan ikinci bir yolum var (ve bunun gibi hack'lerden kaçınmaya çalışıyorum). Diziyi kanaldan önce önüne virgül yerleştirebilirsiniz. Bu, tek öğe olduğu başka bir diziye kaydırılır $data , bu nedenle dış diziyi çıkardıktan sonra yeniden $data eşlenmemiş hale getiririz.

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

Dizi döndürme

Dizilerin bu unwrapping işlevinden çıkış yaptığınızda veya değer döndürdiğinizde de gerçekleşir. Çıktıyı bir değişkene atarsanız yine de bir dizi alabilirsiniz, bu nedenle bu genellikle bir sorun değildir.

Yakalama, yeni bir diziniz olmasıdır. Bu bir sorun olduğunda, veya return ,$array kullanarak bu sorunu çözebilirsinizWrite-Output -NoEnumerate $array.

Başka birşey var mı?

Biliyorum, bunların hepsi çok fazla. Umarım her okuduğunuzda bu makaleden bir şeyler öğrenirsiniz ve uzun bir süre boyunca sizin için iyi bir referans olur. Bunu yararlı bulduysanız, lütfen bundan değer alabileceğini düşündüğünüz diğer kişilerle paylaşın.

Buradan, karma tablolarla ilgili yazdığım benzer bir gönderiye göz atmanızı öneririm.