BLACK FRIDAY! Slevy až 80 % jsou všude. Tak je nepropásni a přejdi do rostoucího IT oboru!
The real BF 2020

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 [email protected]()
    • 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:.
  • 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[email protected](1,2,3)
$Pole+=4

Indexování prvků

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Každý prvek v poli je indexován číslem od 0poč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[email protected](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[email protected](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[email protected](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[email protected](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[email protected](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.


 

Předchozí článek
PowerShell - Typy výstupu
Všechny články v sekci
PowerShell
Článek pro vás napsal Vojtěch Kašný
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Aktivity (3)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!