Minden, amit tudni akart a tömbökről

A tömbök a legtöbb programozási nyelv alapvető nyelvi funkciója. Ezek olyan értékek vagy objektumok gyűjteményei, amelyeket nehéz elkerülni. Vessünk egy pillantást a tömbökre és az általuk kínált lehetőségekre.

Feljegyzés

A cikk eredeti verziója @KevinMarquette által írt blogon jelent meg. A PowerShell csapata köszönjük Kevinnek, hogy megosztotta velünk ezt a tartalmat. Kérjük, nézze meg a blogját a PowerShellExplained.com.

Mi a tömb?

Először egy alapszintű technikai leírással fogom kezdeni, hogy milyen tömbök vannak, és hogyan használják őket a legtöbb programozási nyelv, mielőtt a PowerShell más módon használja őket.

A tömbök olyan adatszerkezetek, amelyek több elemből álló gyűjteményként szolgálnak. A tömbön keresztül iterálhat, vagy index használatával elérheti az egyes elemeket. A tömb a memória szekvenciális adattömbjeként jön létre, ahol minden érték közvetlenül a másik mellett van tárolva.

Minden részletet meg fogok érinteni, ahogy haladunk.

Alapszintű használat

Mivel a tömbök a PowerShell egyik alapvető funkciója, létezik egy egyszerű szintaxis, amellyel a PowerShellben dolgozhat velük.

Tömb létrehozása

Üres tömb hozható létre a következő használatával: @()

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

Létrehozhatunk egy tömböt, és csak zárójelekbe @() helyezzük őket értékekkel.

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

PS> $data
Zero
One
Two
Three

Ez a tömb 4 elemet tartalmaz. Amikor meghívjuk a változót $data , megjelenik az elemek listája. Ha sztringek tömbje, akkor sztringenként egy sort kapunk.

Több sorban deklarálhatunk tömböt. A vessző ebben az esetben nem kötelező, és általában kimarad.

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

Inkább több sorban deklarálom a tömböket. A több elem használata esetén nem csak könnyebben olvasható, hanem a korábbi verziókhoz képest is egyszerűbben összehasonlítható a forrásvezérlő használata esetén.

Egyéb szintaxis

Általánosan ismert, hogy @() ez egy tömb létrehozásának szintaxisa, de a vesszővel tagolt listák az idő nagy részében működnek.

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

Írási kimenet tömbök létrehozásához

Egy jó kis trükk, amit érdemes megemlíteni, hogy a Write-Output konzolon gyorsan létrehozhat sztringeket.

$data = Write-Output Zero One Two Three

Ez azért hasznos, mert nem kell idézőjeleket elhelyeznie a sztringek körül, amikor a paraméter sztringeket fogad el. Én soha nem csinál ez egy szkript, de ez tisztességes játék a konzolon.

Elemek elérése

Most, hogy már rendelkezik elemeket tartalmazó tömbdel, érdemes lehet elérni és frissíteni ezeket az elemeket.

Eltolás

Az egyes elemek eléréséhez a szögletes zárójeleket [] 0-tól kezdődő eltolási értékkel használjuk. Így kapjuk meg a tömb első elemét:

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

Azért használjuk itt a nullát, mert az első elem a lista elején van, ezért 0 elem eltolásával jutunk hozzá. A második elem eléréséhez 1-et kell használnunk az első elem kihagyásához.

PS> $data[1]
One

Ez azt jelentené, hogy az utolsó elem a 3. eltolásnál van.

PS> $data[3]
Three

Index

Most már láthatja, miért választottam ki azokat az értékeket, amelyeket ebben a példában tettem. Azért vezettem be ezt eltolásként, mert valójában ez az, de ezt az eltolást gyakrabban nevezik indexnek. Egy index, amely a következő időpontban 0kezdődik: . A cikk további részében indexnek fogom hívni az eltolást.

Speciális indexelési trükkök

A legtöbb nyelvben csak egyetlen számot adhat meg indexként, és egyetlen elemet kap vissza. A PowerShell sokkal rugalmasabb. Egyszerre több indexet is használhat. Az indexek listájának megadásával több elemet is kiválaszthatunk.

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

A rendszer az elemeket a megadott indexek sorrendje alapján adja vissza. Ha duplikál egy indexet, az elemet mindkét alkalommal megkapja.

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

A beépített .. operátorral megadhatja a számok sorozatát.

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

Ez fordítva is működik.

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

Negatív indexértékek használatával eltolást végezhet a végponttól. Ha tehát a lista utolsó elemére van szüksége, használhatja -1a következőt:

PS> $data[-1]
Three

Egy szó az óvatosságról itt az .. operátorral. A sorrend 0..-1 és -1..0 a kiértékelés az értékekre 0,-1 és -1,0a . Ha elfelejti ezt a részletet, könnyen láthatja $data[0..-1] és gondolhatja, hogy az összes elemet számba venné. $data[0..-1] ugyanazt az értéket adja meg, mint $data[0,-1] a tömb első és utolsó elemének megadásával (és a többi érték egyikével sem). Íme egy nagyobb példa:

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

Ez ugyanaz, mint:

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

Határon kívül

A legtöbb nyelvben, ha egy olyan elem indexét próbálja elérni, amely a tömb végén található, valamilyen hiba vagy kivétel jelenik meg. A PowerShell csendben semmit sem ad vissza.

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

Null tömbbe nem indexelhető

Ha a változó tömbként $null van indexelve, kivételt System.Management.Automation.RuntimeException kap az üzenettel Cannot index into a null array.

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

Ezért győződjön meg arról, hogy a tömbök nem $null azok, mielőtt megpróbál hozzáférni a bennük lévő elemekhez.

Count

A tömbök és más gyűjtemények számláló tulajdonsága jelzi, hogy hány elem van a tömbben.

PS> $data.count
4

A PowerShell 3.0 egy darabszám tulajdonságot adott hozzá a legtöbb objektumhoz. lehet egyetlen objektum, és meg kell adnia egy darab 1.

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

Még számláló tulajdonsága is $null van, kivéve, hogy visszaadja 0.

PS> $null.count
0

Van néhány trap itt, hogy én majd újra, amikor foglalkozom ellenőrzése $null , vagy üres tömbök később ebben a cikkben.

Egyenkénti hibák

Gyakori programozási hiba jön létre, mert a tömbök a 0. indexnél kezdődnek. Az egyszeri hibák kétféleképpen vezethetők be.

Az első a szellemi gondolkodás szeretné a második tételt, és használja az indexet 2 , és valóban kap a harmadik tétel. Vagy ha arra gondol, hogy négy elemből áll, és az utolsó elemet szeretné, így a darabszám használatával elérheti az utolsó elemet.

$data[ $data.count ]

A PowerShell tökéletesen örömmel teszi ezt, és pontosan megadja, hogy milyen elem létezik a 4. indexben: $null. Önnek vagy a -1 fentebb megismertnek kell lennie$data.count - 1.

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

Itt szerezheti be az utolsó elemet az -1 index használatával.

PS> $data[ -1 ]
Three

Lee Dailey arra is rámutatott, hogy a maximális indexszám lekérésére használhatjuk $data.GetUpperBound(0) .

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

A második leggyakoribb módszer a lista iterálása, és nem a megfelelő időben való leállás. Ezt akkor fogom újra áttekinteni, amikor a for hurok használatáról beszélünk.

Elemek frissítése

Ugyanezzel az indexel frissíthetjük a tömb meglévő elemeit. Ez közvetlen hozzáférést biztosít az egyes elemek frissítéséhez.

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

Ha az utolsó elemen túllépő elemet próbálunk frissíteni, hibaüzenet jelenik Index was outside the bounds of the array. meg.

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

Ezt később újra áttekintem, amikor arról beszélek, hogyan lehet nagyobb tömböt létrehozni.

Iteráció

Előfordulhat, hogy egy adott ponton végig kell járnia vagy iterálnia kell a teljes listát, és végre kell hajtania néhány műveletet a tömb egyes elemeihez.

Folyamat

A tömbök és a PowerShell-folyamat egymásnak vannak szánva. Ez az értékek feldolgozásának egyik legegyszerűbb módja. Amikor átad egy tömböt egy folyamatnak, a tömb minden egyes elemét egyenként dolgozza fel a rendszer.

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

Ha még nem láttad $PSItem , csak tudd, hogy ez ugyanaz, mint $_. Bármelyiket használhatja, mert mindkettő a folyamat aktuális objektumát jelöli.

ForEach hurok

A ForEach hurok jól működik a gyűjteményekkel. A szintaxis használata: foreach ( <variable> in <collection> )

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

ForEach metódus

Általában elfelejtem ezt, de az egyszerű műveletekhez jól működik. A PowerShell lehetővé teszi egy gyűjtemény meghívását .ForEach() .

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

A .foreach() parancsprogram egy szkriptblokkot tartalmazó paramétert vesz fel. Elvetheti a zárójeleket, és csak megadhatja a szkriptblokkot.

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

Ez egy kevésbé ismert szintaxis, de ugyanúgy működik. Ez a foreach módszer a PowerShell 4.0-ban lett hozzáadva.

A for hurok

A for ciklust a legtöbb más nyelven erősen használják, de a PowerShellben nem sok. Ha ezt látja, az gyakran a tömbök sétáltatásának kontextusában történik.

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

Az első dolog, amit teszünk, hogy inicializáljuk $index a .0 Ezután hozzáadjuk azokat a feltételeket, amelyeknek $index kisebbnek kell lenniük.$data.count Végül azt határozzuk meg, hogy minden ciklus során növelni kell az indexet 1. Ebben az esetben $index++ a rövid .$index = $index + 1 A formátum operátor (-f) a kimeneti sztring értékének beszúrására $data[$index] szolgál.

Amikor hurkot for használ, különös figyelmet kell fordítania a feltételre. Én is itt használtam $index -lt $data.count . Könnyen lekérheti a feltételt kissé helytelenül, ha egyszeri hibát kap a logikában. Használ, $index -le $data.count vagy $index -lt ($data.count - 1) mindig olyan enyhén rossz. Ez azt eredményezné, hogy az eredmény túl sok vagy túl kevés elemet dolgoz fel. Ez a klasszikus off-by-one hiba.

Ciklus váltása

Ezt könnyű figyelmen kívül hagyni. Ha tömböt ad meg egy kapcsolóutasításhoz, az ellenőrzi a tömb minden elemét.

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

Sok jó dolgot tehetünk a kapcsoló utasításával. Van egy másik cikket szentelt erre.

Értékek frissítése

Ha a tömb sztringek vagy egész számok (értéktípusok) gyűjteménye, előfordulhat, hogy érdemes frissíteni a tömb értékeit, miközben hurkolja őket. A fenti hurkok többsége egy változót használ a ciklusban, amely az érték másolatát tartalmazza. Ha frissíti ezt a változót, a tömb eredeti értéke nem frissül.

Az utasítás alól kivételt képez a for hurok. Ha be szeretne járni egy tömböt, és frissíteni szeretné benne az értékeket, akkor a for ciklus az, amit keres.

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

Ez a példa egy index szerinti értéket vesz igénybe, módosít néhány módosítást, majd ugyanazt az indexet használja a visszaosztáshoz.

Objektumok tömbjei

Eddig csak egy értéktípust helyeztünk el egy tömbben, de a tömbök is tartalmazhatnak objektumokat.

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

Sok parancsmag tömbökként adja vissza az objektumok gyűjteményeit, amikor egy változóhoz rendeli őket.

$processList = Get-Process

A már említett alapvető funkciók továbbra is érvényesek az objektumtömbökre, néhány részletre érdemes rámutatni.

Tulajdonságok elérése

Az index használatával ugyanúgy érhetünk el egy gyűjtemény egyes elemeit, mint az értéktípusok esetében.

PS> $data[0]

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

A tulajdonságokat közvetlenül is elérhetjük és frissíthetjük.

PS> $data[0].FirstName

Kevin

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

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

Tömbtulajdonságok

Általában az összes tulajdonság eléréséhez a teljes listát a következőképpen kell számbavétele:

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

Marquette
Doe

Vagy a Select-Object -ExpandProperty parancsmag használatával.

PS> $data | Select-Object -ExpandProperty LastName

Marquette
Doe

A PowerShell azonban lehetővé teszi számunkra a közvetlen kérést LastName . A PowerShell felsorolja az összeset számunkra, és egy tiszta listát ad vissza.

PS> $data.LastName

Marquette
Doe

Az enumerálás továbbra is megtörténik, de nem látjuk a mögöttes összetettségét.

Where-Object filtering

Itt Where-Object érkezik be, hogy az objektum tulajdonságai alapján szűrhessük és kiválaszthassuk, hogy mit szeretnénk kivenni a tömbből.

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

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

Ugyanezt a lekérdezést megírhatjuk, hogy lekérjük a FirstName keresett lekérdezést.

$data | Where FirstName -eq Kevin

Hol()

A tömbökben van egy Where() metódus, amely lehetővé teszi a szűrő megadását scriptblock .

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

Ez a funkció a PowerShell 4.0-s verzióban lett hozzáadva.

Objektumok frissítése hurkokban

Értéktípusok esetén a tömb frissítésének egyetlen módja egy ciklus használata, mivel az érték cseréjéhez ismerni kell az indexet. Több lehetőségünk van az objektumokkal, mert referenciatípusok. Íme egy gyors példa:

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

Ez a hurok a tömb minden objektumát végigjárja $data . Mivel az objektumok hivatkozástípusok, a $person változó pontosan ugyanarra az objektumra hivatkozik, amely a tömbben található. A tulajdonságok frissítése tehát nem frissíti az eredetit.

Így sem tudja lecserélni az egész objektumot. Ha új objektumot próbál hozzárendelni a $person változóhoz, a változóhivatkozást olyanra frissíti, amely már nem az eredeti objektumra mutat a tömbben. Ez nem úgy működik, mint amire számított:

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

Operátorok

A PowerShell operátorai tömbökön is működnek. Néhányuk kissé másképp működik.

-Csatlakozzon

Az -join operátor a legnyilvánvalóbb, ezért nézzük meg először. Szeretem az operátort -join , és gyakran használom. A tömb összes elemét összekapcsolja a megadott karakterrel vagy sztringgel.

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

Az operátor egyik funkciója, hogy kezeli az -join egyes elemeket.

PS> 1 -join '-'
1

Ezt a naplózásban és részletes üzenetekben használom.

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

-csatlakozás $array

Itt van egy okos trükk, amit Lee Dailey mutatott nekem. Ha valaha is szeretne csatlakozni mindent nélkül elválasztó, ahelyett, hogy ezt tegye:

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

A tömböt paraméterként használhatja -join előtag nélkül. Tekintse meg ezt a példát, és nézze meg, hogy miről beszélek.

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

-replace and -split

A többi operátor szereti -replace és -split végrehajtja a tömb egyes elemeit. Nem mondhatom, hogy valaha is így használtam őket, de itt van egy példa.

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

-Tartalmaz

Az -contains operátor lehetővé teszi az értékek tömbjének ellenőrzését, hogy az tartalmaz-e megadott értéket.

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

-in

Ha egyetlen értékkel rendelkezik, amelyet ellenőrizni szeretne, hogy egyezik-e a több érték egyikével, használhatja az operátort -in . Az érték a bal oldalon, a tömb pedig az operátor jobb oldalán található.

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

Ez költséges lehet, ha a lista nagy. Gyakran használok regex mintát, ha több értéket is ellenőrizek.

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

PS> 'green' -match $pattern
True

-eq és -ne

Az egyenlőség és a tömbök bonyolulttá tehetik. Ha a tömb a bal oldalon van, minden elem össze lesz hasonlítva. A visszatérés Truehelyett az egyező objektumot adja vissza.

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

Az operátor használatakor -ne az összes olyan értéket megkapjuk, amely nem egyenlő az értékünkkel.

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

Ha ezt egy if() utasításban használja, a visszaadott érték egy True érték. Ha nem ad vissza értéket, akkor ez egy False érték. Mindkét következő utasítás kiértékelése a következő lesz True.

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

Ezt egy pillanat alatt megismétlem, amikor a tesztelésről $nullbeszélünk.

-Mérkőzés

Az -match operátor megpróbálja egyeztetni a gyűjtemény egyes elemeit.

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

Ha egyetlen értékkel használja -match , a speciális változók $Matches egyezésadatokkal lesznek feltöltve. Nem ez a helyzet, ha egy tömböt így dolgoznak fel.

Ugyanezt a megközelítést is alkalmazhatjuk a következővel Select-String: .

$servers | Select-String SQL

Én egy közelebbi pillantást Select-String,-match és a $matches változó egy másik post nevű The many ways to use regex.

$null vagy üres

A tömbök tesztelése $null vagy üressége bonyolult lehet. Íme a tömbök gyakori csapdái.

Ez az állítás egy pillantásra úgy tűnik, hogy működnie kell.

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

De most átnéztem, hogyan -eq ellenőrzik a tömb egyes elemeit. Így több elemből álló tömb is lehet egyetlen $null értékkel, és a $true

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

Ezért ajánlott az operátor bal oldalára helyezni $null az operátort. Ez a forgatókönyv nem probléma.

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

A $null tömbök nem azonosak az üres tömbökéval. Ha tudja, hogy van egy tömbje, ellenőrizze a benne lévő objektumok számát. Ha a tömb az $null, akkor a szám .0

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

Van még egy csapda, amit ki kell figyelni. Akkor is használhatja az count objektumot, ha egyetlen objektummal rendelkezik, kivéve, ha az objektum egy PSCustomObject. Ez egy hiba, amely a PowerShell 6.1-ben van javítva. Ez jó hír, de sokan még mindig az 5.1-en vannak, és vigyázni kell rá.

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

Ha továbbra is a PowerShell 5.1-en dolgozik, az objektumot egy tömbbe burkolhatja, mielőtt ellenőrizené a darabszámot, hogy pontos számot kapjon.

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

A biztonságos lejátszáshoz ellenőrizze, hogy van-e $null, majd ellenőrizze a darabszámot.

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

Minden –eq

Nemrég láttam valakit, aki megkérdezte , hogyan ellenőrizheti, hogy egy tömb minden értéke egyezik-e egy adott értékkel. Reddit felhasználó /u/bis volt ez az okos megoldás , amely ellenőrzi a helytelen értékeket, majd tükrözi az eredményt.

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

Hozzáadás tömbökhöz

Ezen a ponton kezd elgondolkozni azon, hogyan adhat hozzá elemeket egy tömbhöz. A gyors válasz az, hogy nem lehet. A tömbök rögzített méretűek a memóriában. Ha növelnie kell, vagy hozzá kell adnia egy elemet, létre kell hoznia egy új tömböt, és át kell másolnia az összes értéket a régi tömbből. Ez sok munkának hangzik, azonban a PowerShell elrejti az új tömb létrehozásának összetettségét. A PowerShell a tömbök összeadási operátorát (+) implementálja.

Feljegyzés

A PowerShell nem valósít meg kivonási műveletet. Ha rugalmas alternatívát szeretne használni egy tömbhöz, általános List objektumot kell használnia.

Tömb hozzáadása

Az összeadás operátort tömbökkel is használhatjuk új tömbök létrehozásához. A következő két tömböt tekintve:

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

Összeadhatjuk őket, hogy új tömböt kapjunk.

PS> $first + $second

Zero
One
Two
Three

Plusz egyenlő +=

Létrehozhatunk egy új tömböt a helyén, és az alábbi módon adhatunk hozzá egy elemet:

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

Ne feledje, hogy minden alkalommal, amikor azt használja += , hogy duplikálja és létrehoz egy új tömböt. Ez nem jelent problémát a kis adathalmazok esetében, de rendkívül rosszul skálázható.

Folyamat-hozzárendelés

Bármely folyamat eredményeit hozzárendelheti egy változóhoz. Tömb, ha több elemet tartalmaz.

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

Általában a folyamat használatakor a tipikus PowerShell-egysorosok jutnak eszébe. A folyamatot utasításokkal és más hurkokkal foreach() is használhatjuk. Így ahelyett, hogy elemeket adnánk hozzá egy tömbhöz egy hurokban, az elemeket a folyamatba helyezhetjük.

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

Tömbtípusok

A Rendszer alapértelmezés szerint típusként [PSObject[]] hoz létre egy tömböt a PowerShellben. Ez lehetővé teszi, hogy bármilyen típusú objektumot vagy értéket tartalmazzon. Ez azért működik, mert minden a típustól PSObject öröklődik.

Erősen beírt tömbök

Bármilyen típusú tömböt létrehozhat hasonló szintaxissal. Erősen beírt tömb létrehozásakor az csak a megadott típusú értékeket vagy objektumokat tartalmazhat.

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

Az elemek tömbhöz való hozzáadása az egyik legnagyobb korlátozás, de van néhány más gyűjtemény is, amelyekhez a probléma megoldásához fordulhatunk.

Ez ArrayList általában az egyik első dolog, amire gondolunk, amikor olyan tömbre van szükségünk, amellyel gyorsabban dolgozhatunk. Úgy működik, mint egy objektumtömb minden olyan helyen, ahol szükségünk van rá, de gyorsan kezeli az elemek hozzáadását.

Az alábbiakban bemutatjuk, hogyan hozhatunk létre és ArrayList adhatunk hozzá elemeket.

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

A .NET-be hívjuk ezt a típust. Ebben az esetben az alapértelmezett konstruktort használjuk annak létrehozásához. Ezután meghívjuk a Add metódust egy elem hozzáadásához.

Azért használom [void] a sor elején, hogy elnyomom a visszatérési kódot. Néhány .NET-hívás ezt teszi, és váratlan kimenetet hozhat létre.

Ha a tömbben csak sztringek vannak, akkor tekintse meg a StringBuilder használatát is. Ez szinte ugyanaz a dolog, de van néhány módszer, amely csak a sztringek kezelésére. A StringBuilder kifejezetten teljesítményre tervezett.

Gyakran előfordul, hogy az emberek tömbökről lépnek ArrayList át. De olyan időkből származik, amikor a C# nem rendelkezik általános támogatással. Az ArrayList általános támogatás elavult List[]

Általános lista

Az általános típus egy speciális C#-típus, amely egy általánosított osztályt határoz meg, a felhasználó pedig a létrehozáskor használt adattípusokat határozza meg. Ha tehát számokat vagy sztringeket szeretne listázni, akkor meg kell határoznia int , hogy szeretne-e listát vagy string típusokat.

A sztringek listájának létrehozása az alábbiak szerint történik.

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

Vagy egy számlistát.

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

Egy meglévő tömböt egy ilyen listára helyezhetünk anélkül, hogy először létrehoznánk az objektumot:

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

A szintaxist a PowerShell 5-ös és újabb verzióban található utasítással using namespace lerövidíthetjük. Az using utasításnak a szkript első sorának kell lennie. A névtér deklarálásával a PowerShell lehetővé teszi az adattípusok elhagyását, amikor hivatkozik rájuk.

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

Így sokkal használhatóbbá válik List .

Ön is rendelkezik hasonló Add módszerrel. A Tömblista függvénytől eltérően nincs visszatérési érték a Add metóduson, így nem kell hozzá tartoznunk void .

$myList.Add(10)

És továbbra is hozzáférhetünk az elemekhez, mint más tömbök.

PS> $myList[-1]
10

Listázás[PSObject]

Bármilyen típusú listával rendelkezhet, de ha nem ismeri az objektumok típusát, [List[PSObject]] használhatja őket az objektumok elhelyezésére.

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

Remove()

Az ArrayList általános és az általános List[] is támogatja az elemek eltávolítását a gyűjteményből.

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

Az értéktípusok használatakor eltávolítja az elsőt a listából. Az érték eltávolításához újra és újra meghívhatja. Ha rendelkezik hivatkozástípusokkal, meg kell adnia az eltávolítani kívánt objektumot.

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

Az eltávolítási true módszer akkor ad vissza, ha megtalálta és eltávolította az elemet a gyűjteményből.

További gyűjtemények

Sok más gyűjtemény is használható, de ezek a jó általános tömbcserék. Ha többet szeretne megtudni ezekről a lehetőségekről, tekintse meg ezt a Mark Kraus által összeállított Gistet.

Egyéb árnyalatok

Most, hogy lefedtem az összes fő funkciót, íme néhány további dolog, amit meg akartam említeni, mielőtt becsomagolom ezt.

Előre méretezett tömbök

Említettem, hogy a tömb méretét nem módosíthatja a létrehozás után. Előre meghatározott méretű tömböt úgy hozhatunk létre, hogy meghívjuk a new($size) konstruktorhoz.

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

Tömbök szorzása

Egy érdekes kis trükk az, hogy megszorozhat egy tömböt egész számmá.

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

Inicializálás 0-val

Gyakori forgatókönyv, hogy minden nullával rendelkező tömböt szeretne létrehozni. Ha csak egész számokat szeretne megadni, akkor az egész számok erősen beírt tömbje alapértelmezés szerint az összes nullára vonatkozik.

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

Erre is használhatjuk a szorzó trükköt.

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

A szép dolog a szorzó trükk, hogy használhat bármilyen értéket. Így ha inkább az 255 alapértelmezett érték, ez lenne a jó módja annak.

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

Beágyazott tömbök

A tömbön belüli tömböt beágyazott tömbnek nevezzük. Ezeket nem használom sokat a PowerShellben, de más nyelveken is használtam őket. Fontolja meg tömbök tömbjének használatát, ha az adatok rácsszerű mintához hasonló módon illeszkednek.

Kétféleképpen hozhatunk létre kétdimenziós tömböt.

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

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

A vessző nagyon fontos ezekben a példákban. Adtam egy korábbi példát egy normál tömb több sorban, ahol a vessző nem volt kötelező. A többdimenziós tömbök esetében ez nem így van.

Az index jelölésének használata kissé megváltozik most, hogy beágyazott tömböt használunk. $data A fentiek alapján így érnénk el a 3 értéket.

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

Adjon hozzá egy zárójelkészletet a tömbök beágyazásának minden szintjéhez. Az első szögletes zárójelek a külső legtöbb tömbhöz vannak, majd onnan kell befelé haladni.

Write-Output -NoEnumerate

A PowerShell szereti a tömbök kiírását vagy számbavételét. Ez a PowerShell folyamathasználatának alapvető aspektusa, de vannak olyan esetek, amikor nem szeretné, hogy ez megtörténjen.

Gyakran pipa objektumokat, hogy Get-Member többet tudjon meg róluk. Amikor egy tömböt hozzá csövezek, az le lesz bontva, és a Get-Member a tömb tagjait látja, nem pedig a tényleges tömböt.

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

A tömb kibontásának megakadályozásához használhatja Write-Output -NoEnumeratea következőt: .

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

Van egy második módja, hogy inkább egy hack (és megpróbálom elkerülni hack, mint ez). A vesszőt a tömb elé helyezheti, mielőtt becsövezené. Ez egy másik tömbbe burkolódik $data , ahol ez az egyetlen elem, így a külső tömb kibontása után újra $data le lesz bontva.

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

Tömb visszaadva

A tömbök ilyen megszüntetése akkor is előfordul, ha függvényből ad ki vagy ad vissza értékeket. A tömböt akkor is lekérheti, ha a kimenetet egy változóhoz rendeli, így ez általában nem jelent problémát.

A fogás az, hogy van egy új tömb. Ha ez valaha is probléma, használhatja Write-Output -NoEnumerate $array vagy return ,$array megkerülheti.

Bármi egyéb?

Tudom, hogy sok mindent be kell venni. Remélem, hogy tanulni valamit ebből a cikkből minden alkalommal, amikor elolvassa, és hogy kiderül, hogy egy jó hivatkozás az Ön számára hosszú ideig, hogy jöjjön. Ha hasznosnak találta ezt a lehetőséget, ossza meg másokkal, akikről úgy gondolja, hogy hasznos lehet belőle.

Innen azt javaslom, hogy nézd meg egy hasonló post, hogy írtam a kivonatolók.