Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Pole jsou základní součástí většiny programovacích jazyků. Jedná se o kolekci hodnot nebo objektů, kterým se obtížně vyhněte. Pojďme se blíže podívat na pole a všechno, co nabízejí.
Poznámka:
původní verze tohoto článku se objevila na blogu napsaného @KevinMarquette. Tým PowerShellu děkujeme Kevinovi za sdílení tohoto obsahu s námi. Prosím, podívejte se na jeho blog na PowerShellExplained.com.
Co je pole?
Začnem základním technickým popisem polí a jejich používání většinou programovacích jazyků, než se přesunu na jiné způsoby, jak je PowerShell využívá.
Pole je datová struktura, která slouží jako kolekce více položek. Pomocí indexu můžete iterovat pole nebo přistupovat k jednotlivým položkám. Pole se vytvoří jako sekvenční blok paměti, kde každá hodnota je uložena přímo vedle druhé.
S každou z těchto podrobností se budu zabývat postupně.
Základní použití
Vzhledem k tomu, že pole jsou taková základní funkce PowerShellu, existuje jednoduchá syntaxe pro práci s nimi v PowerShellu.
Vytvořte pole
Prázdné pole lze vytvořit pomocí @()
PS> $data = @()
PS> $data.Count
0
Můžeme vytvořit pole a naplnit ho hodnotami jednoduše tak, že je umístíme do závorek @().
PS> $data = @('Zero','One','Two','Three')
PS> $data.Count
4
PS> $data
Zero
One
Two
Three
Toto pole obsahuje 4 položky. Když zavoláme proměnnou $data, zobrazí se seznam položek. Pokud se jedná o pole řetězců, získáme jeden řádek na jeden řetězec.
Můžeme deklarovat pole na více řádcích. Čárka je v tomto případě volitelná a obecně se vynechává.
$data = @(
'Zero'
'One'
'Two'
'Three'
)
Raději deklaruji pole na více řádcích. Při použití správy zdrojového kódu se nejen snadněji čte, když máte více položek, ale také usnadňuje porovnání s předchozími verzemi.
Jiná syntaxe
Běžně se rozumí, že @() je syntaxe pro vytvoření pole, ale seznamy oddělené čárkami fungují většinu času.
$data = 'Zero','One','Two','Three'
Write-Output k vytváření polí
Jeden skvělý malý trik stojí za zmínku je, že můžete použít Write-Output k rychlému vytváření řetězců v konzole.
$data = Write-Output Zero One Two Three
To je užitečné, protože když parametr přijímá řetězce, nemusíte do řetězců zadávat uvozovky. Nikdy bych to neudělal ve skriptu, ale v konzoli je to férová hra.
Přístup k položkám
Teď, když máte pole s položkami, můžete k těmto položkám přistupovat a aktualizovat je.
Offset
Pro přístup k jednotlivým položkám používáme hranaté závorky [] s hodnotou posunu počínaje hodnotou 0. Takto získáme první položku v našem poli:
PS> $data = 'Zero','One','Two','Three'
PS> $data[0]
Zero
Důvodem, proč zde použijeme nulu, je to, že první položka je na začátku seznamu, takže k tomu použijeme posun 0 položek. Abychom se dostali k druhé položce, museli bychom pro přeskočení první položky použít posun 1.
PS> $data[1]
One
To by znamenalo, že poslední položka je na offsetu 3.
PS> $data[3]
Three
Rejstřík
Teď vidíte, proč jsem vybral hodnoty, které jsem udělal pro tento příklad. Tento posun jsem představil jako posun, protože to je to, co skutečně je, ale tento posun se častěji označuje jako index. Index, který začíná na 0. Pro zbytek tohoto článku budu nazývat offset indexem.
Speciální triky indexu
Ve většině jazyků můžete zadat pouze jedno číslo jako index a získáte zpět jednu položku. PowerShell je mnohem flexibilnější. Můžete použít více indexů najednou. Zadáním seznamu indexů můžeme vybrat několik položek.
PS> $data[0,2,3]
Zero
Two
Three
Položky se vrátí na základě pořadí zadaných indexů. Pokud duplikujete index, získáte tuto položku dvakrát.
PS> $data[3,0,3]
Three
Zero
Three
Pomocí integrovaného operátoru .. můžeme zadat posloupnost čísel.
PS> $data[1..3]
One
Two
Three
To funguje i obráceně.
PS> $data[3..1]
Three
Two
One
Záporné hodnoty indexu můžete použít k posunu od konce. Pokud tedy potřebujete poslední položku v seznamu, můžete použít -1.
PS> $data[-1]
Three
Zde je jedno slovo varování k operátoru ... Sekvence 0..-1 a -1..0 se vyhodnocuje na hodnoty 0,-1 a -1,0. Je snadné vidět $data[0..-1] a myslet si, že by se výčet vztahoval na všechny položky, pokud zapomenete tento detail.
$data[0..-1] vám poskytne stejnou hodnotu jako $data[0,-1] tím, že získáte první a poslední položku v matici (a žádnou z ostatních hodnot). Tady je větší příklad:
PS> $a = 1,2,3,4,5,6,7,8
PS> $a[2..-1]
3
2
1
8
To je stejné jako:
PS> $a[2,1,0,-1]
3
2
1
8
Mimo hranice
Pokud se ve většině jazyků pokusíte získat přístup k indexu položky, která je za koncem pole, dojde k nějaké chybě nebo výjimce. PowerShell tiše nevrátí nic.
PS> $null -eq $data[9000]
True
Nelze indexovat do pole s hodnotou null.
Pokud je proměnná $null a pokusíte se ji indexovat jako pole, zobrazí se System.Management.Automation.RuntimeException výjimka se zprávou Cannot index into a null array.
PS> $empty = $null
PS> $empty[0]
Error: Cannot index into a null array.
Než se tedy pokusíte o přístup k prvkům uvnitř, ujistěte se, že pole nejsou $null.
Počet
Pole a další kolekce mají Count vlastnost, která vám řekne, kolik položek je v poli.
PS> $data.Count
4
PowerShell 3.0 přidal do většiny objektů vlastnost Count. Můžete mít jediný objekt a ten by vám měl poskytnout počet 1.
PS> $date = Get-Date
PS> $date.Count
1
I $null má vlastnost Count s tím rozdílem, že vrací 0.
PS> $null.Count
0
Zde jsou některé pasti, kterými se budu zabývat při kontrole $null nebo prázdných polí později v tomto článku.
Chyby o jedno
Vytvoří se běžná programovací chyba, protože pole začínají indexem 0. Chyby typu off-by-one mohou být zavedeny dvěma způsoby.
První je, když si mentálně představujete, že chcete druhou položku, a použijete index 2, ale ve skutečnosti získáte třetí položku. Nebo si myslíte, že máte čtyři položky a chcete poslední položku, takže počet použijete pro přístup k poslední položce.
$data[ $data.Count ]
PowerShell vám to dokonale umožní a poskytne vám přesně tu položku, která se nachází na indexu 4: $null. Měli byste používat $data.Count - 1 nebo -1, o které jsme se dozvěděli výše.
PS> $data[ $data.Count - 1 ]
Three
Tady můžete použít index -1 k získání posledního prvku.
PS> $data[ -1 ]
Three
Lee Dailey mi také ukázal, že můžeme použít $data.GetUpperBound(0) k získání maximálního indexu.
PS> $data.GetUpperBound(0)
3
PS> $data[ $data.GetUpperBound(0) ]
Three
Druhým nejběžnějším způsobem je iterace seznamu a nezastavování ve správný čas. Znovu se k tomu vrátím, až budeme mluvit o použití smyčky for.
Aktualizace položek
Stejný index můžeme použít k aktualizaci existujících položek v poli. To nám dává přímý přístup k aktualizaci jednotlivých položek.
$data[2] = 'dos'
$data[3] = 'tres'
Pokud se pokusíme aktualizovat položku, která je za posledním prvkem, zobrazí se Index was outside the bounds of the array. chyba.
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
Později se k tomu vrátím, až budu mluvit o tom, jak pole zvětšit.
Iterace
V určitém okamžiku možná budete muset procházet nebo iterovat celý seznam a provádět určité akce pro každou položku v poli.
Potrubí
Pole a kanál PowerShellu jsou určené pro sebe. Toto je jeden z nejjednodušších způsobů zpracování těchto hodnot. Když předáte pole do kanálu, každá položka uvnitř pole se zpracuje jednotlivě.
PS> $data = 'Zero','One','Two','Three'
PS> $data | ForEach-Object {"Item: [$PSItem]"}
Item: [Zero]
Item: [One]
Item: [Two]
Item: [Three]
Pokud jste předtím neviděli $PSItem, stačí vědět, že je to totéž jako $_. Můžete použít jeden z nich, protože oba představují aktuální objekt v kanálu.
Smyčka ForEach
Smyčka foreach funguje dobře s kolekcemi. Použití syntaxe: foreach ( <variable> in <collection> )
foreach ( $node in $data )
{
"Item: [$node]"
}
Metoda ForEach
Mám tendenci zapomenout na tuto, ale funguje dobře pro jednoduché operace. PowerShell umožňuje volat ForEach() v kolekci.
PS> $data.ForEach({"Item [$PSItem]"})
Item [Zero]
Item [One]
Item [Two]
Item [Three]
ForEach() přebírá parametr, který je blokem skriptu. Závorky můžete vypustit a stačí zadat blok skriptu.
$data.ForEach{"Item [$PSItem]"}
Jedná se o méně známou syntaxi, ale funguje stejně. Tato metoda ForEach byla přidána v PowerShellu 4.0.
For smyčka
Smyčka for se hodně používá ve většině ostatních jazyků, ale v PowerShellu ji moc nevidíte. Když ho vidíte, často je to v kontextu procházení pole.
for ( $index = 0; $index -lt $data.Count; $index++)
{
"Item: [{0}]" -f $data[$index]
}
První věc, kterou uděláme, je inicializovat $index na 0. Pak přidáme podmínku, že $index musí být menší než $data.Count. Nakonec určíme, že pokaždé, když opakujeme, musíme zvýšit index o 1. V tomto případě $index++ je zkratka pro $index = $index + 1. Operátor formátu (-f) slouží k vložení hodnoty $data[$index] do výstupního řetězce.
Kdykoli používáte smyčku for, věnujte zvláštní pozornost podmínce. Použil jsem $index -lt $data.Count tady. Je snadné, když se podmínka trochu špatně nastaví, což vede k chybě typu off-by-one v logice. Použití $index -le $data.Count nebo $index -lt ($data.Count - 1) je vždy trochu nesprávné. To by způsobilo, že váš výsledek zpracuje příliš mnoho nebo příliš málo položek. Jedná se o klasickou chybu typu off-by-one.
Přepínací smyčka
To je ten, který je snadno přehlédnutelný. Pokud zadáte pole příkazu switch, zkontroluje každou položku v poli.
$data = 'Zero','One','Two','Three'
switch( $data )
{
'One'
{
'Tock'
}
'Three'
{
'Tock'
}
Default
{
'Tick'
}
}
Tick
Tock
Tick
Tock
S příkazem switch můžeme dělat spoustu skvělých věcí. Mám další článek věnovaný tomuto.
Aktualizace hodnot
Pokud je pole kolekcí řetězců nebo celých čísel (hodnotových typů), někdy můžete chtít aktualizovat hodnoty v poli, jakmile je smyčte. Většina výše uvedených smyček používá proměnnou ve smyčce, která obsahuje kopii hodnoty. Pokud tuto proměnnou aktualizujete, původní hodnota v poli se neaktualizuje.
Výjimkou k tomuto tvrzení je smyčka for. Pokud chcete procházet pole a aktualizovat hodnoty uvnitř, pak smyčka for je to, co hledáte.
for ( $index = 0; $index -lt $data.Count; $index++ )
{
$data[$index] = "Item: [{0}]" -f $data[$index]
}
Tento příklad vezme hodnotu podle indexu, provede několik změn a pak tento stejný index použije k jeho přiřazení zpět.
Pole objektů
Zatím jedinou věcí, kterou jsme umístili do pole, je typ hodnoty, ale pole můžou obsahovat i objekty.
$data = @(
[pscustomobject]@{FirstName='Kevin';LastName='Marquette'}
[pscustomobject]@{FirstName='John'; LastName='Doe'}
)
Mnoho rutin vrací kolekce objektů jako pole, když je přiřadíte proměnné.
$processList = Get-Process
Všechny základní funkce, o kterých jsme už mluvili, se stále vztahují na pole objektů s několika podrobnostmi, které stojí za zmínku.
Přístup k vlastnostem
Index můžeme použít pro přístup k jednotlivé položce v kolekci stejně jako u typů hodnot.
PS> $data[0]
FirstName LastName
----- ----
Kevin Marquette
K vlastnostem můžeme přistupovat a aktualizovat je přímo.
PS> $data[0].FirstName
Kevin
PS> $data[0].FirstName = 'Jay'
PS> $data[0]
FirstName LastName
----- ----
Jay Marquette
Vlastnosti pole
Pokud chcete získat přístup ke všem vlastnostem, obvykle byste museli vytvořit výčet celého seznamu, jako je tento:
PS> $data | ForEach-Object {$_.LastName}
Marquette
Doe
Nebo pomocí cmdletu Select-Object -ExpandProperty.
PS> $data | Select-Object -ExpandProperty LastName
Marquette
Doe
PowerShell nám nabízí možnost přímo požádat o LastName. PowerShell vytvoří výčet všech pro nás a vrátí čistý seznam.
PS> $data.LastName
Marquette
Doe
Výčet stále probíhá, ale nevidíme za ním složitost.
Filtrování Where-Object
To je místo, kde Where-Object přichází, abychom mohli filtrovat a vybírat, co chceme z pole na základě vlastností objektu.
PS> $data | Where-Object {$_.FirstName -eq 'Kevin'}
FirstName LastName
----- ----
Kevin Marquette
Můžeme napsat stejný dotaz, abychom získali FirstName, které hledáme.
$data | where FirstName -EQ Kevin
Where()
Pole mají Where() metodu, která umožňuje zadat scriptblock pro filtr.
$data.Where({$_.FirstName -eq 'Kevin'})
Tato funkce byla přidána v PowerShellu 4.0.
Aktualizace objektů ve smyčkách
U typů hodnot je jediným způsobem, jak pole aktualizovat, použít smyčku for, protože potřebujeme znát index, který nahradí hodnotu. S objekty máme více možností, protože se jedná o odkazové typy. Tady je rychlý příklad:
foreach($person in $data)
{
$person.FirstName = 'Kevin'
}
Tato smyčka prochází všechny objekty v poli $data. Vzhledem k tomu, že objekty jsou odkazové typy, $person proměnná odkazuje na stejný objekt, který je v poli. Aktualizace vlastností tak aktualizují původní.
Tímto způsobem stále nemůžete nahradit celý objekt. Pokud se pokusíte přiřadit nový objekt k proměnné $person, aktualizujete odkaz proměnné na něco jiného, co už neukazuje na původní objekt v poli. To nefunguje tak, jak byste očekávali:
foreach($person in $data)
{
$person = [pscustomobject]@{
FirstName='Kevin'
LastName='Marquette'
}
}
Operátoři
Operátory v PowerShellu pracují také na polích. Některé z nich fungují trochu jinak.
-připojit
Operátor -join je nejzřejmější, takže se na něj podívejme nejdříve. Líbí se mi operátor -join a často ho používám. Spojí všechny prvky v poli se zadaným znakem nebo řetězcem.
PS> $data = @(1,2,3,4)
PS> $data -join '-'
1-2-3-4
PS> $data -join ','
1,2,3,4
Jednou z funkcí, které se mi líbí o operátoru -join, je, že zpracovává jednotlivé položky.
PS> 1 -join '-'
1
Používám to v rámci protokolování a podrobných zpráv.
PS> $data = @(1,2,3,4)
PS> "Data is $($data -join ',')."
Data is 1,2,3,4.
-join $array
Tady je chytrý trik, který mi Lee Dailey ukázal. Pokud byste někdy chtěli spojit všechno bez oddělovače, můžete místo toho udělat toto:
PS> $data = @(1,2,3,4)
PS> $data -join $null
1234
Můžete použít pole s parametrem -join bez předpony. Podívejte se na tento příklad a zjistěte, o čem mluvím.
PS> $data = @(1,2,3,4)
PS> -join $data
1234
-replace a -split
Ostatní operátory, jako jsou -replace a -split, se spouštějí u každé položky v poli. Nemůžu říct, že jsem je někdy použil tímto způsobem, ale tady je příklad.
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
-obsahuje
Operátor -contains umožňuje zkontrolovat matici hodnot a zjistit, jestli obsahuje zadanou hodnotu.
PS> $data = @('red','green','blue')
PS> $data -contains 'green'
True
-v
Pokud máte jednu hodnotu, kterou chcete ověřit, odpovídá jedné z několika hodnot, můžete použít operátor -in. Hodnota by byla na levé straně a pole na pravé straně operátoru.
PS> $data = @('red','green','blue')
PS> 'green' -in $data
True
To může být nákladné, pokud je seznam velký. Často používám vzor regulárních výrazů, pokud kontrolujem více než několik hodnot.
PS> $data = @('red','green','blue')
PS> $pattern = "^({0})$" -f ($data -join '|')
PS> $pattern
^(red|green|blue)$
PS> 'green' -match $pattern
True
-eq a -ne
Rovnost a pole můžou být komplikované. Když je pole na levé straně, porovná se každá položka. Místo vrácení Truevrátí objekt, který odpovídá.
PS> $data = @('red','green','blue')
PS> $data -eq 'green'
green
Když použijete operátor -ne, získáme všechny hodnoty, které se nerovnají naší hodnotě.
PS> $data = @('red','green','blue')
PS> $data -ne 'green'
red
blue
Pokud to použijete v příkazu if(), vrácená hodnota je hodnota True. Pokud se nevrátí žádná hodnota, jedná se o False hodnotu. Oba tyto další příkazy se vyhodnotí jako True.
$data = @('red','green','blue')
if ( $data -eq 'green' )
{
'Green was found'
}
if ( $data -ne 'green' )
{
'And green was not found'
}
Za chvíli se k tomu vrátím, až si promluvíme o testování na $null.
-utkání
Operátor -match se pokusí spárovat každou položku v kolekci.
PS> $servers = @(
'LAX-SQL-01'
'LAX-API-01'
'ATX-SQL-01'
'ATX-API-01'
)
PS> $servers -match 'SQL'
LAX-SQL-01
ATX-SQL-01
Když použijete -match s jednou hodnotou, naplní se speciální proměnná $Matches informacemi o shodě. To není případ, kdy se pole zpracuje tímto způsobem.
Můžeme použít stejný přístup s Select-String.
$servers | Select-String SQL
Podrobněji se podívám na Select-String,-match a $Matches proměnnou v jiném příspěvku nazvaném Mnoho způsobů použití regex.
$null nebo prázdné
Testování $null nebo prázdných polí může být složité. Tady jsou běžné pasti s poli.
Na první pohled toto stanovisko vypadá, jako by mělo fungovat.
if ( $array -eq $null)
{
'Array is $null'
}
Ale právě jsem přešel, jak -eq kontroluje každou položku v poli. Můžeme mít pole s několika položkami a jednou hodnotou $null, které by se vyhodnotilo jako $true.
$array = @('one',$null,'three')
if ( $array -eq $null)
{
'I think Array is $null, but I would be wrong'
}
Proto je osvědčeným postupem umístit $null na levou stranu operátoru. Díky tomu tento scénář není problém.
if ( $null -eq $array )
{
'Array actually is $null'
}
Pole $null není totéž jako prázdné pole. Pokud víte, že máte pole, zkontrolujte počet objektů v něm. Pokud je pole $null, počet je 0.
if ( $array.Count -gt 0 )
{
"Array isn't empty"
}
Je tu ještě jedna past, na kterou si musíte dávat pozor. Můžete použít Count i v případě, že máte jeden objekt, pokud tento objekt není PSCustomObject. Jedná se o chybu, která je opravená v PowerShellu 6.1.
To je dobrá zpráva, ale mnoho lidí je pořád na verzi 5.1 a musí si na to dát pozor.
PS> $object = [pscustomobject]@{Name='TestObject'}
PS> $object.Count
$null
Pokud stále používáte PowerShell 5.1, můžete objekt zabalit do pole, než zkontrolujete počet, abyste získali přesný počet.
if ( @($array).Count -gt 0 )
{
"Array isn't empty"
}
Pro jistotu zkontrolujte $nulla pak zkontrolujte počet.
if ( $null -ne $array -and @($array).Count -gt 0 )
{
"Array isn't empty"
}
Všechny -eq
Nedávno jsem viděl někoho na Reddit zeptat se, jak ověřit, že každá hodnota v poli odpovídá dané hodnotě. Uživatel Reddit u/bis měl toto chytré řešení, které se zaměřuje na nesprávné hodnoty a obrátí výsledek.
$results = Test-Something
if ( -not ( $results -ne 'Passed') )
{
'All results a Passed'
}
Přidání do polí
V tomto okamžiku začínáte přemýšlet o tom, jak přidat položky do pole. Rychlá odpověď je, že nemůžete. Pole má pevnou velikost v paměti. Pokud ho potřebujete zvětšit nebo do ní přidat jednu položku, musíte vytvořit nové pole a zkopírovat všechny hodnoty ze starého pole. To zní jako spousta práce, ale PowerShell skrývá složitost vytváření nového pole. PowerShell používá operátor sčítání (+) pro pole.
Poznámka:
PowerShell neimplementuje operaci odčítání. Pokud chcete flexibilní alternativu k poli, musíte použít obecný objekt List.
Přidání pole
K vytvoření nového pole můžeme použít operátor sčítání s poli. Takže vzhledem k těmto dvěma polím:
$first = @(
'Zero'
'One'
)
$second = @(
'Two'
'Three'
)
Můžeme je sečíst, abychom získali nové pole.
PS> $first + $second
Zero
One
Two
Three
Plus se rovná +=
Můžeme vytvořit nové pole a přidat do ní položku takto:
$data = @(
'Zero'
'One'
'Two'
'Three'
)
$data += 'four'
Nezapomeňte, že pokaždé, když použijete +=, že duplikujete a vytváříte nové pole. Nejedná se o problém u malých datových sad, ale velmi špatně se škáluje.
Přiřazení pipeline
Výsledky libovolného kanálu můžete přiřadit do proměnné. Jedná se o pole, pokud obsahuje více položek.
$array = 1..5 | ForEach-Object {
"ATX-SQL-$PSItem"
}
Obvykle, když uvažujeme o použití pipeline, myslíme na typické jednořádkové příkazy PowerShellu. Můžeme využít kanál pomocí příkazů foreach() a dalších smyček. Takže místo přidávání položek do pole ve smyčce můžeme položky vložit do pipeline.
$array = foreach ( $node in (1..5))
{
"ATX-SQL-$node"
}
Typy polí
Ve výchozím nastavení se pole v PowerShellu vytvoří jako typ [psobject[]]. To umožňuje, aby obsahoval jakýkoli typ objektu nebo hodnoty. To funguje, protože vše je zděděno z typu PSObject.
Pole se silným typováním
Pole libovolného typu můžete vytvořit pomocí podobné syntaxe. Když vytvoříte pole silného typu, může obsahovat pouze hodnoty nebo objekty zadaného typu.
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
Přidání položek do pole je jedním z jeho největších omezení, ale existuje několik dalších kolekcí, které můžeme využít k vyřešení tohoto problému.
ArrayList je často jednou z prvních věcí, která nás napadne, když potřebujeme pole, s nímž lze pracovat rychleji. Funguje jako pole objektů, které potřebujeme, ale zpracovává rychlé přidávání položek.
Tady je postup, jak vytvoříme ArrayList a přidáme do něj položky.
$myarray = [System.Collections.ArrayList]::new()
[void]$myArray.Add('Value')
Využíváme .NET k získání tohoto typu. V tomto případě k jeho vytvoření používáme výchozí konstruktor. Potom zavoláme metodu Add, která do ní přidá položku.
Důvodem, proč používám [void] na začátku řádku je potlačení návratového kódu. Některá volání .NET to dělají a můžou vytvořit neočekávaný výstup.
Pokud jsou jedinými daty, která máte v poli, řetězce, pak se také podívejte na použití StringBuilder. Je to skoro stejná věc, ale má některé metody, které jsou jen pro práci s řetězci.
StringBuilder je speciálně navržen pro výkon.
Často vídáme, jak se lidé přesouvají z polí do ArrayList. Ale pochází z doby, kdy jazyk C# neměl obecnou podporu.
ArrayList je zastaralý ve prospěch obecného List[]
Obecný seznam
Obecný typ je speciální typ v jazyce C#, který definuje generalizovanou třídu a uživatel určuje datové typy, které používá při vytváření. Pokud tedy chcete seznam čísel nebo řetězců, nadefinujte, že chcete seznam typů int nebo string.
Zde je postup, jak vytvořit seznam pro řetězce.
$mylist = [System.Collections.Generic.List[string]]::new()
Nebo seznam čísel.
$mylist = [System.Collections.Generic.List[int]]::new()
Existující pole můžeme přetypovat na seznam podobný tomuto, aniž bychom nejprve vytvořili objekt:
$mylist = [System.Collections.Generic.List[int]]@(1,2,3)
Syntaxi můžeme zkrátit příkazem using namespace v PowerShellu 5 a novějším. Příkaz using musí být prvním řádkem skriptu. Když deklarujete obor názvů, PowerShell vám umožní vynechat jeho použití při odkazování na datové typy.
using namespace System.Collections.Generic
$myList = [List[int]]@(1,2,3)
Díky tomu je List mnohem použitelnější.
Máte k dispozici podobnou metodu Add. Na rozdíl od ArrayList není v metodě Add žádná návratová hodnota, takže ji nemusíme void.
$myList.Add(10)
A stále můžeme přistupovat k prvkům, jako jsou jiná pole.
PS> $myList[-1]
10
List[psobject]
Můžete mít seznam libovolného typu, ale pokud neznáte typ objektů, můžete je použít [List[psobject]] k jejich zahrnutí.
$list = [List[psobject]]::new()
Remove()
ArrayList i obecný List[] podporují odebrání položek z kolekce.
using namespace System.Collections.Generic
$myList = [List[string]]@('Zero','One','Two','Three')
[void]$myList.Remove("Two")
Zero
One
Three
Při práci s typy hodnot odebere první ze seznamu. Můžete ji znovu a znovu použít, abyste tuto hodnotu stále odstraňovali. Pokud máte odkazové typy, musíte zadat objekt, který chcete odebrat.
[List[System.Management.Automation.PSDriveInfo]]$drives = Get-PSDrive
$drives.Remove($drives[2])
$delete = $drives[2]
$drives.Remove($delete)
Metoda remove vrátí true, pokud byla schopna najít a odebrat položku z kolekce.
Další kolekce
Existuje mnoho dalších kolekcí, které lze použít, ale tyto jsou dobrá alternativa k obecným polím. Pokud se chcete dozvědět více o těchto možnostech, podívejte se na tento Gist, který Mark Kraus připravil.
Jiné drobné odlišnosti
Teď, když jsem probral všechny hlavní funkce, tady je několik dalších věcí, které jsem chtěl zmínit předtím, než jsem to zabalil.
Pole s pevnou velikostí
Zmínil jsem se, že po vytvoření pole nemůžete změnit jeho velikost. Pole předem určené velikosti můžeme vytvořit tak, že ho zavoláme pomocí konstruktoru new($size).
$data = [Object[]]::new(4)
$data.Count
4
Násobení polí
Zajímavým malým trikem je, že pole můžete vynásobit celým číslem.
PS> $data = @('red','green','blue')
PS> $data * 3
red
green
blue
red
green
blue
red
green
blue
Inicializace pomocí 0
Běžným scénářem je, že chcete vytvořit pole se všemi nulami. Pokud budete mít jenom celá čísla, pole celých čísel s pevným typem ve výchozím nastavení nastaví na všechny nuly.
PS> [int[]]::new(4)
0
0
0
0
Můžeme také použít násobicí trik k tomu.
PS> $data = @(0) * 4
PS> $data
0
0
0
0
Výhodou triku s násobením je, že můžete použít libovolnou hodnotu. Takže pokud byste raději jako výchozí hodnotu měli 255, bylo by to dobrý způsob, jak to udělat.
PS> $data = @(255) * 4
PS> $data
255
255
255
255
Vnořené pole
Pole uvnitř pole se nazývá vnořené pole. V PowerShellu je moc nepoužívám, ale použil jsem je více v jiných jazycích. Zvažte použití pole polí, když se vaše data hodí do mřížkového vzoru.
Tady jsou dva způsoby, jak můžeme vytvořit dvojrozměrné pole.
$data = @(@(1,2,3),@(4,5,6),@(7,8,9))
$data2 = @(
@(1,2,3),
@(4,5,6),
@(7,8,9)
)
Čárka je v těchto příkladech velmi důležitá. Uvedl jsem dřívější příklad normálního pole na více řádcích, kde byla čárka nepovinná. To není případ s multidimenzionálním polem.
Způsob, jakým používáme zápis indexu, se mírně změní, když máme vnořené pole. Při použití výše uvedeného $data bychom získali přístup k hodnotě 3.
PS> $outside = 0
PS> $inside = 2
PS> $data[$outside][$inside]
3
Přidejte sadu hranatých závorek pro každou úroveň vnoření pole. První sada hranatých závorek je určená pro nejvzdálenější pole a pak pracujete směrem dovnitř.
Write-Output -NoEnumerate
PowerShell rád rozbalovat a vypisovat pole. Jedná se o základní aspekt toho, jak PowerShell používá kanál, ale někdy nechcete, aby se to stalo.
Běžně přesměrovávám objekty do Get-Member, abych se o nich dozvěděl víc. Když předám pole, dojde k jeho rozbalování a Get-Member uvidí členy pole, nikoli skutečné pole.
PS> $data = @('red','green','blue')
PS> $data | Get-Member
TypeName: System.String
...
Chcete-li zabránit rozbalení pole, můžete použít Write-Output -NoEnumerate.
PS> Write-Output -NoEnumerate $data | Get-Member
TypeName: System.Object[]
...
Mám druhý způsob, který je spíše vychytávka (a snažím se vyhnout vychytávkám, jako je tato). Před polem můžete umístit čárku. To zabalí $data do jiného pole, kde je jediným prvkem, takže po rozbalení vnějšího pole získáme zpět $data rozbalený.
PS> ,$data | Get-Member
TypeName: System.Object[]
...
Vrátit pole
K tomuto rozbalování polí dochází také při výstupu nebo vrácení hodnot z funkce. Pokud přiřadíte výstup proměnné, stále můžete získat pole, takže to obvykle není problém.
Háček je v tom, že máte nové pole. Pokud se jedná o problém, můžete ho obejít pomocí Write-Output -NoEnumerate $array nebo return ,$array.
Cokoli jiného?
Vím, že je toho hodně k pochopení. Doufám, že se pokaždé, když tento článek čtete, něco naučíte a že se pro vás stane dobrým odkazem na dlouhou dobu. Pokud jste zjistili, že to může být užitečné, sdílejte ho s ostatními, o které si myslíte, že z toho může získat hodnotu.
Odsud bych vám doporučil podívat se na podobný příspěvek, který jsem napsal o hashtables.