NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

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 +=.
  • 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=@(1,2,3)
$Pole+=4

Indexování prvků

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=@(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.


 

Předchozí článek
PowerShell - Typy výstupu
Všechny články v sekci
PowerShell
Přeskočit článek
(nedoporučujeme)
PowerShell - Kolekce objektů, II. část
Článek pro vás napsal Vojtěch Kašný
Avatar
Uživatelské hodnocení:
17 hlasů
Aktivity