Sdílet prostřednictvím


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í Truevrá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-Stringa-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 $nullpole , 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.