Všechno, co jste chtěli vědět o polích
Pole jsou základní jazykovou funkcí 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é @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ždým z těchto podrobností se budu dotýkat, jak jdeme.
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ření pole
Prázdné pole lze vytvořit pomocí @()
PS> $data = @()
PS> $data.count
0
Můžeme vytvořit matici a osévat ji hodnotami 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ě nepovinná a obecně vynechá.
$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 @()
syntaxe pro vytvoření pole, ale seznamy oddělené čárkami fungují většinu času.
$data = 'Zero','One','Two','Three'
Write-Output to create arrays
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 udělal ve skriptu, ale je to spravedlivé hry v konzole.
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.
Odsazení
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 posunu 3.
PS> $data[3]
Three
Index
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 zavolám posun indexu.
Speciální triky indexu
Ve většinějazykůch 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 oběma časy.
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
Jedno slovo opatrnosti zde s operátorem ..
. 0..-1
Posloupnost a -1..0
vyhodnocení hodnot 0,-1
a -1,0
. Je snadné vidět $data[0..-1]
a myslet si, že by výčet všech položek, pokud zapomenete tento detail. $data[0..-1]
vrátí stejnou hodnotu jako $data[0,-1]
tím, že vám poskytne první a poslední položku v matici (a žádné 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 bezobslužně nevrátí nic.
PS> $null -eq $data[9000]
True
Nelze indexovat do pole s hodnotou null.
Pokud je $null
proměnná a pokusíte se ji indexovat jako pole, zobrazí se výjimka se zprávou System.Management.Automation.RuntimeException
Cannot index into a null array
.
PS> $empty = $null
PS> $empty[0]
Error: Cannot index into a null array.
Proto se ujistěte, že pole nejsou $null
před pokusem o přístup k prvkům uvnitř.
Počet
Pole a další kolekce mají vlastnost count, která říká, 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 jeden objekt a měl by vám dát počet .1
PS> $date = Get-Date
PS> $date.count
1
Dokonce $null
má vlastnost count s výjimkou toho, že vrátí 0
.
PS> $null.count
0
Tady jsou nějaké pasti, které budu znovu navštívit, když probírám kontrolu $null
nebo prázdné pole později v tomto článku.
Chyby mimo 1
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 mentálně přemýšlet, že chcete druhou položku a použít index 2
a opravdu získat 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 je naprosto šťastný, že vám to umožní a poskytne vám přesně to, co položka existuje v indexu 4: $null
. Měli byste používat $data.count - 1
nebo -1
o tom, co jsme se dozvěděli výše.
PS> $data[ $data.count - 1 ]
Three
Tady můžete pomocí indexu -1
získat poslední prvek.
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 číslo.
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 připojím, až budeme mluvit o používání 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 Index was outside the bounds of the array.
, zobrazí se 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 znovu připojím, až budu mluvit o tom, jak zvětšit pole.
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.
Kanál
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
dobře funguje 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()
kolekci.
PS> $data.foreach({"Item [$PSItem]"})
Item [Zero]
Item [One]
Item [Two]
Item [Three]
Přebírá .foreach()
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 foreach
metoda byla přidána v PowerShellu 4.0.
Smyčka for
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, která $index
musí být menší než $data.count
. Nakonec určíme, že pokaždé, když budeme opakovat, že 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 do výstupního $data[$index]
řetězce.
Vždy, když používáte smyčku for
, věnujte zvláštní pozornost konfliktu. Použil $index -lt $data.count
jsem tady. Je snadné, když se podmínka mírně pokazí, aby se v logice zobrazila chyba typu off-by-one. Použití $index -le $data.count
nebo $index -lt ($data.count - 1)
jsou někdy tak trochu špatně. 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 do 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 pro tento příkaz je smyčka for
. Pokud chcete procházet pole a aktualizovat hodnoty uvnitř, 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í rutiny Select-Object -ExpandProperty
.
PS> $data | Select-Object -ExpandProperty LastName
Marquette
Doe
PowerShell nám ale nabízí možnost požádat LastName
přímo. 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í objektů
To je místo, kde Where-Object
přichází, abychom mohli filtrovat a vybrat, 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 hledaný FirstName
dotaz.
$data | Where FirstName -eq Kevin
Where()
Pole mají pro ně metodu Where()
, 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čce
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 $data
v poli. Vzhledem k tomu, že objekty jsou odkazové typy, $person
proměnná odkazuje na úplně 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 k proměnné nový objekt $person
, aktualizujete odkaz na proměnnou na něco jiného, co již odkazuje 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átory
Operátory v PowerShellu pracují také na polích. Některé z nich fungují trochu jinak.
-připojit
Operátor -join
je nejjasnější, takže se na něj podíváme jako na první. Líbí se -join
mi operátor 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 uvnitř protokolování a podrobné zprávy.
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ísto toho, abyste to udělali:
PS> $data = @(1,2,3,4)
PS> $data -join $null
1234
S polem můžete použít -join
jako parametr 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 and -split
Ostatní operátory se podobají -replace
a -split
spouštějí pro každou položku 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 -in
operátor. 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 složité. Když je pole na levé straně, porovná se každá položka. Místo vrácení True
vrátí objekt, který odpovídá.
PS> $data = @('red','green','blue')
PS> $data -eq 'green'
green
Když použijete -ne
operátor, 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 if()
příkazu, vrátí se True
hodnota. Pokud se nevrátí žádná hodnota, jedná se o False
hodnotu. Oba následující 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 znovu připojím, až budeme mluvit o testování pro $null
.
-utkání
Operátor -match
se pokusí shodovat s každou položkou 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
a-match
proměnnou v jiném příspěvku $matches
nazvaném Mnoho způsobů použití regulárního výrazu.
$null nebo prázdné
Testování pro $null
nebo prázdná pole může být složité. Tady jsou běžné pasti s poli.
Na první pohled tento příkaz vypadá, jako by měl 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 tedy mít pole několika položek s jednou hodnotou $null a vyhodnotí se 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 levou $null
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 $null
pole , počet je 0
.
if ( $array.count -gt 0 )
{
"Array isn't empty"
}
Je tu ještě jedna past, na které je potřeba se podívat. 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 stále na 5,1 a musí se na to dívat.
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"
}
Chcete-li plně hrát v bezpečí, zkontrolujte $null
, a pak zkontrolujte počet.
if ( $null -ne $array -and @($array).count -gt 0 )
{
"Array isn't empty"
}
All -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 u/bis
Reddit měl toto chytré řešení, které kontroluje nesprávné hodnoty a výsledek pak překlopí.
$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 je pevná 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 implementuje 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ý List
objekt.
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 +=
duplikování a vytvoření nového pole. Nejedná se o problém u malých datových sad, ale velmi špatně se škáluje.
Přiřazení kanálu
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ž si myslíme, že používáme kanál, si myslíme typické one-linery PowerShellu. Kanál můžeme využít s foreach()
příkazy a dalšími smyčkami. Takže místo přidávání položek do pole ve smyčce můžeme přesunout položky do kanálu.
$array = foreach ( $node in (1..5))
{
"ATX-SQL-$node"
}
Typy polí
Ve výchozím nastavení se pole v PowerShellu [PSObject[]]
vytvoří jako typ. To umožňuje, aby obsahoval jakýkoli typ objektu nebo hodnoty. To funguje, protože vše je zděděno z PSObject
typu.
Pole se silnými typy
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 obrátit na řešení tohoto problému.
Často ArrayList
se jedná o jednu z prvních věcí, o které si myslíme, když potřebujeme pole, se kterým se pracuje rychleji. Funguje jako pole objektů, které potřebujeme, ale zpracovává rychlé přidávání položek.
Tady je postup, jak do ArrayList
něj vytvoříme a přidáme položky.
$myarray = [System.Collections.ArrayList]::new()
[void]$myArray.Add('Value')
K získání tohoto typu voláme rozhraní .NET. V tomto případě k jeho vytvoření používáme výchozí konstruktor. Potom zavoláme metodu Add
pro přidání položky do ní.
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, podívejte se také na použití StringBuilderu. Je to skoro stejná věc, ale má některé metody, které jsou jen pro práci s řetězci. Je StringBuilder
speciálně navržen pro výkon.
Lidé se často přesouvají z ArrayList
polí. Ale pochází z doby, kdy jazyk C# neměl obecnou podporu. Podpora obecného typu je ArrayList
zastaralá. 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í. Takže pokud chcete seznam čísel nebo řetězců, definovali byste, že chcete seznam int
nebo string
typy.
Tady 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 v PowerShellu using namespace
5 a novějším. Příkaz using
musí být prvním řádkem skriptu. Když deklarujete obor názvů, PowerShell ho při odkazování na datové typy nechá mimo.
using namespace System.Collections.Generic
$myList = [List[int]]@(1,2,3)
Díky tomu je List
mnohem využitelnější.
Máte k dispozici podobnou Add
metodu. Na rozdíl od ArrayList neexistuje pro metodu Add
žádná návratová hodnota, takže ji nepotřebujeme 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()
Oba ArrayList
typy List[]
podporují odebírá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. Pokud chcete tuto hodnotu odebrat, můžete ji zavolat znovu a znovu. 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 jedná se o dobré nahrazení obecných polí. Pokud se chcete dozvědět více o těchto možnostech, podívejte se na tento Gist , který Mark Kraus dal dohromady.
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.
Předpřipravená pole
Zmínil jsem se, že po vytvoření pole nemůžete změnit velikost pole. Pole předem určené velikosti můžeme vytvořit tak, že ji zavoláme pomocí konstruktoru new($size)
.
$data = [Object[]]::new(4)
$data.count
4
Násobení polí
Zajímavým malým trikem je, že matici můžete vynásobit celé číslo.
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 celočísel se silným typem ve výchozím nastavení nastaví na všechny nuly.
PS> [int[]]::new(4)
0
0
0
0
K tomu můžeme použít i násobení triku.
PS> $data = @(0) * 4
PS> $data
0
0
0
0
Pěkná věc o násobení trik je, že můžete použít libovolnou hodnotu. Takže pokud byste raději měli 255
jako výchozí hodnotu, 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á matice. 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 vejdou do mřížky, jako je vzor.
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á. Dal jsem dřívější příklad normální matice na více řádcích, kde čárka byla 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. Pomocí výše uvedeného $data
postupu 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 vnější většinu polí a pak pracujete v cestě odtud.
Write-Output -NoEnumerate
PowerShell se rád rozbalí nebo vypíše pole. Jedná se o základní aspekt způsobu, jakým PowerShell kanál používá, ale někdy to nechcete, aby k tomu došlo.
Běžně píšu objekty, abych Get-Member
se o nich dozvěděl více. Když matici předám, zobrazí se rozbalené pole 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 více hack (a snažím se vyhnout hackerům, jako je to). Před polem můžete před polem umístit čárku. Tím se zabalí $data
do jiného pole, kde je jediným prvkem, takže po rozbalení vnějšího pole se vrátíme zpět $data
.
PS> ,$data | Get-Member
TypeName: System.Object[]
...
Vrácení pole
K tomuto přepsá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.
Zachytávání je, že máte nové pole. Pokud se jedná o nějaký problém, můžete ho použít Write-Output -NoEnumerate $array
nebo return ,$array
obejít.
Cokoli jiného?
Vím, že je to všechno, co se má vzít. Doufám, že se něco z tohoto článku naučíte pokaždé, když ho čtete a že se ukázalo, že je pro vás dobrý odkaz 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.