Lekce 7 - PowerShell - Kolekce objektů
V předchozí lekci, PowerShell - Typy výstupu, jsme se seznámili s PowerShell výstupy, naučili se dané typy výstupu používat v praxi a také jak tyto výstupy přesměrovat.
V dnešní lekci kurzu PowerShell frameworku se seznámíme s různými typy kolekcí PowerShellu.
Statické pole
(System.Array
)
Pole je základní typ kolekce v PowerShellu a je deklarováno pomocí
výrazu @()
. Toto pole může obsahovat jak čísla, řetězce,
objekty tak i další pole objektů. V tomto případě se již bavíme o
vícerozměrném poli.
Defaultně umí PowerShell automaticky určit datový typ
objektu, nicméně někdy můžeme chtít jiný datový typ, než nám nabízí
PowerShell. V tomto případě můžeme vynutit datový typ pomocí
[<datatype>]
.
Jako příklad můžeme uvést přetypování řetězce
([string]
) na pole ([array]
):
[array]$Var='tohle bude pole'.
Pole čísel lze deklarovat i dynamicky pomocí rozsahu, např.
$Arr=1..500
.
Pole může být deklarováno:
- buď ručně, pomocí již zmíněného výrazu
@()
, například$Pole=@()
- V tomto případě se jedná o statické pole a prvky (či elementy) se do
tohoto pole přidávají pomocí operátoru
+=
.
- V tomto případě se jedná o statické pole a prvky (či elementy) se do
tohoto pole přidávají pomocí operátoru
- pomocí příkazu, který vrací pole objektů, například
$Pole=Get-ChildItem C:
- Zde se také jedná o statické pole, nicméně jeho velikost a obsah
určuje výstup z příkazu, v tomto případě
Get-ChildItem C:
.
- Zde se také jedná o statické pole, nicméně jeho velikost a obsah
určuje výstup z příkazu, v tomto případě
- pomocí vynucení datového typu
[array]
, například[array]$Pole=Get-Date
- Opět se jedná o statické pole, v tomto případě byl tento datový typ vynucen.
Základní operace s prvky ve statickém poli
Statické pole neumožňuje odebrání prvku z tohoto pole.
Procházení prvků v poli nám umožňují příkazy
cyklů ForEach
a Foreach-Object
. Jaký je mezi
těmito příkazy rozdíl se dozvíme v jiné lekci.
Přidání dalšího prvku
Přidání dalšího prvku do statického pole se provádí operátorem
+=
:
$Pole=@(1,2,3) $Pole+=4
Indexování prvků
Každý prvek v poli je indexován číslem od 0
až
počet prvků -1
a jsou indexovány v takovém pořadí, v jakém
byly do pole přidány:
$Pole[0] #vypíše prvek na první pozici $Pole[0..2] #vypíše první až třetí prvek $Pole[0..$Pole.Count] #vypíše všechny prvky v poli (defaultní akce při zavolání proměnné $Pole)
Procházení prvků v poli
Ke zpracování prvků v poli slouží dva příkazy, a to
ForEach
a ForEach-Object
:
ForEach ($i in $Pole){ Write-Output "--> pracuji s hodnotou '$i'" } # ForEach-Object: $Pole | ForEach-Object { Write-Output ("--> pracuji s hodnotou '{0}'" -f $_) }
Ochrana datového typu v poli
Ochrana datového typu v poli se provádí požadovaným datovým typem a
výrazem []
, například výraz [int[]]
znamená, že
pole může obsahovat pouze prvky datového typu int
(celé
číslo). Pokud není určeno jinak, PowerShell neřeší, jaké datové typy
pole obsahuje. V poli tudíž můžou být prvky různých datových typů, jak
je znázorněno na příkladu níže:
$Pole=@(1,'text',(get-date))
Na tomto příkladu můžeme vidět, že pole obsahuje 3 prvky, kde každý
je jiného datového typu. Pokud ovšem chceme, aby v poli byly pouze prvky
určitého datového typu, například pouze pole čísel (int
),
zabezpečíme to tímto výrazem:
[int[]]$PoleInt=@(1,2,3)
Pokud bychom se přeci jen pokusili do toho pole umístit prvek, který nesplňuje datový typ nebo PowerShell nebyl schopen provést konverzi datového typu, PowerShell zahlásí chybu:
Windows PowerShell [int[]]$PoleInt=@(1,2,3,'text') Cannot convert value "text" to type "System.Int32". Error: "Input string was not in a correct format." At line:1 char:1 + [int[]]$PoleInt=@(1,2,3,'text') + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException + FullyQualifiedErrorId : RuntimeException
Pokud ovšem do pole umístíme prvek, který je možno konvertovat,
PowerShell tento prvek zkonvertuje na požadovaný datový typ
[int]
a přidá jej do pole. K tomu, co se děje na pozadí, opět
použijeme příkaz Trace-Command
:
Windows PowerShell Trace-Command -Expression {[int[]]$PoleInt=@(1,2,3,'1')} -Name TypeConversion -PSHost DEBUG: TypeConversion Information: 0 : Converting "System.Object[]" to "System.Int32[]". DEBUG: TypeConversion Information: 0 : Converting "1" to "System.Int32". DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type DEBUG: TypeConversion Information: 0 : Converting "2" to "System.Int32". DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type DEBUG: TypeConversion Information: 0 : Converting "3" to "System.Int32". DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type DEBUG: TypeConversion Information: 0 : Converting "1" to "System.Int32". DEBUG: TypeConversion Information: 0 : Converting to integer.
Ochrana datového typu v poli v praxi
Jako dobrý příklad, kdy využít ochrany datového typu, je například vstupní parametr funkce:
# Tato funkce otestuje port nebo pole portů oproti lokálnímu nebo vzdálenému počítači function Test-TcpPort { param ( [parameter(Mandatory)][int[]]$Port, $ComputerName=$env:COMPUTERNAME ) $Port | ForEach-Object { $PortToTest = $_ $obj = New-Object psobject -Property @{ ComputerName = $ComputerName Port = $PortToTest State = $null } try { [System.Net.Sockets.TcpClient]::new().Connect($ComputerName,$_) $obj.State = 'open' } catch { $obj.State = 'closed' } finally { Write-Output $obj } } }
Na tomto příkladu proběhlo vše v pořádku:
Windows PowerShell Test-TcpPort 3389,80,23 Port ComputerName State ---- ------------ ----- 3389 W0466418 open 80 W0466418 open 23 W0466418 closed
A zde můžeme vidět ochranu datového typu v akci:
Windows PowerShell Test-TcpPort 3389,80,23,'test' Test-TcpPort : Cannot process argument transformation on parameter 'Port'. Cannot convert value "test" to type "System.Int32". Error: "Input string was not in a correct format." At line:1 char:14 + Test-TcpPort 3389,80, 23, 'test' + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Test-TcpPort], ParameterBindingArgumentTransformationException + FullyQualifiedErrorId : ParameterArgumentTransformationError,Test-TcpPort
A příkaz výše ještě jednou, tentokrát s ukázkou toho, jak se PowerShell neúspěšně snaží o konverzi datového typu:
Windows PowerShell Trace-Command -Expression {Test-TcpPort 3389,80, 23, 'test'} -Name TypeConversion -PSHost DEBUG: TypeConversion Information: 0 : Converting "System.Object[]" to "System.Int32[]". DEBUG: TypeConversion Information: 0 : Converting "3389" to "System.Int32". DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type DEBUG: TypeConversion Information: 0 : Converting "80" to "System.Int32". DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type DEBUG: TypeConversion Information: 0 : Converting "23" to "System.Int32". DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type DEBUG: TypeConversion Information: 0 : Converting "test" to "System.Int32". DEBUG: TypeConversion Information: 0 : Converting to integer. DEBUG: TypeConversion Information: 0 : Exception converting to integer: "Input string was not in a correct format.". DEBUG: TypeConversion Information: 0 : Converting to integer passing through double. DEBUG: TypeConversion Information: 0 : Numeric Conversion through System.Double. DEBUG: TypeConversion Information: 0 : Exception converting to integer through double: "Input string was not in a correct format.". DEBUG: TypeConversion Information: 0 : Converting "256" to "System.Int32". DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type DEBUG: TypeConversion Information: 0 : Converting ref to boolean. DEBUG: TypeConversion Information: 0 : Converting ref to boolean. DEBUG: TypeConversion Information: 0 : Converting string to boolean. DEBUG: TypeConversion Information: 0 : Converting ref to boolean. DEBUG: TypeConversion Information: 0 : Converting ref to boolean. DEBUG: TypeConversion Information: 0 : Converting null to boolean. DEBUG: TypeConversion Information: 0 : Converting string to boolean. DEBUG: TypeConversion Information: 0 : Converting string to boolean. DEBUG: TypeConversion Information: 0 : Converting null to boolean. Test-TcpPort : Cannot process argument transformation on parameter 'Port'. Cannot convert value "test" to type "System.Int32". Error: "Input string was not in a correct format." At line:1 char:41 + Trace-Command -Expression {Test-TcpPort 3389,80, 23, 'test'} -Name Ty ... + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Test-TcpPort], ParameterBindingArgumentTransformationException + FullyQualifiedErrorId : ParameterArgumentTransformationError,Test-TcpPort
V další lekci, PowerShell - Kolekce objektů, II. část, se seznámíme s PowerShell kolekcemi a názorně si ukážeme, jak s každou z nich pracovat.