Változóknak
az olyan memóriaterületeket nevezzük,
amelyeket szkriptünkben vagy programunkban névvel jelölünk meg, és a programnak
lehetősége van az adott memóriaterületen található objektum tulajdonságait
kiolvasni, megváltoztatni és a metódusait meghívni. A névvel ellátott
memóriaterület tartalmazhatja közvetlenül az objektumot (érték típusú
változók), illetve tartalmazhat egy hivatkozást (memóriacímet), ami az objektumok
valódi helyét azonosítja (referencia típusú változók). Minden létrehozott
változó számára program adatszegmensén lefoglalódik a megfelelő nagyságú
memóriaterület, amelyet ezután a programból a névre való hivatkozással érhetünk
el, kiolvashatjuk vagy beállíthatjuk annak értékét, illetve referencia esetén a
név segítségével érhetjük el a mutatott objektumot is. Az érték- és referenciatípusok
a PowerShellben gyakorlati szempontból nem különböznek egymástól lényegesen.
A típusok közötti konverzió minden esetben a .NET szabályai szerint történik, ahogyan a későbbi példákban látható. Mi tárolható tehát egy PowerShell változóban? Bármi, amit a .NET a memóriában tárolhat, méghozzá szigorúan típusos formában.
A PowerShell változónevei minden esetben a $ karakterrel kezdődnek (ha önmagában használjuk őket és nem valamilyen változókat kezelő cmdlet segítségével), betűket, számokat és speciális karaktereket is tartalmazhatnak.
Változókat PowerShellben legegyszerűbben a következő formában tudunk létrehozni, használni:
PS C:\> $a = "bcdefghijklmnopqrstuvwxyz"
PS C:\> $b = 12
PS C:\> $c = Get-Location
PS C:\> $a
bcdefghijklmnopqrstuvwxyz
PS C:\> $b
12
PS C:\> $c
Path
----
C:\
Látszik, hogy a változók értékadásához nem kell semmilyen kulcsszót használni, az egyenlőségjel elég az értékadáshoz. A változókhoz nem feltétlenül kell típust rendelni, azaz bármilyen típust, objektumosztályt tartalmazhatnak.
Azt, hogy egy változó éppen milyen típusú értéket tartalmaz a GetType() metódus meghívásával kérdezhetjük le:
PS C:\> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
PS C:\> $b.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
PS C:\> $c.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PathInfo System.Object
Látszik, hogy a $c változónk nem egyszerűen egy szöveget tartalmaz, hanem egy PathInfo típusú objektumot.
A változók típusa nem rögzül, azaz egy String változónak később adhatunk Int32 értéket minden további hiba nélkül, a változó típusa az értékének megfelelően módosul.
PS C:\> $a
bcdefghijklmnopqrstuvwxyz
PS C:\> $a = 22
Ez a megoldás persze nagyon kényelmes, de az automatikus változódeklaráció komoly problémákkal is járhat; minden elgépelésből új, rejtélyes változók születnek, érdekes, de legalábbis nehezen felderíthető futási hibákat okozva. Szkriptek esetén mindenképpen célszerű legalább a hibakeresés fázisában változtatni az alapértelmezett viselkedésen a következő módon:
PS C:\> Set-PSDebug -strict
Ezután a PowerShell hibaüzenetet ad, ha olyan változónevet használunk, amihez korábban még nem rendeltünk értéket:
PS C:\> $a = 2
PS C:\> $a + $b
The variable
'$b' cannot be retrieved because it has not been set.
At line:1
char:8
+ $a + $b
<<<<
+ CategoryInfo : InvalidOperation: (b:Token) [],
RuntimeExceptio
n
+ FullyQualifiedErrorId :
VariableIsUndefined
Az alapértelmezett viselkedés a következő parancs használatával állítható vissza:
PS C:\> Set-PSDebug -off
A változók gyakran nem egyszerű elemeket tartalmaznak, hanem collection-öket (gyűjteményeket, vegyes elemű tömböket) vagy hagyományos tömböket:
[23] PS C:\> $alias = get-alias a*
[24] PS C:\> $alias
CommandType Name Definition
----------- ---- ----------
Alias ac Add-Content
Alias asnp Add-PSSnapIn
A fenti példában az „a” kezdetű aliasok gyűjteménye lesz a $alias változó tartalma. A gyűjteményekkel és tömbökkel később foglalkozom részletesebben.
Változóknak még precízebben is tudunk értéket adni. A set-variable cmdlet nagyon sok opciót biztosít erre:
PS C:\> Set-Variable -Name PI -Value 3.14159265358979 -Option Constant
PS C:\> $PI
3.14159265358979
A fenti példában például a PI nevű változót konstansként hoztam létre, ami azt jelenti, hogy nem engedi felülírni más értékkel, illetve bárhonnan látható ez a változó (scope-pal, azaz láthatósággal később foglalkozom). Ezt még törölni sem lehet a Remove‑Variable cmdlettel.
A Set-Variable cmdletnek van még egy érdekessége is, magyarázatot lehet adni ezzel a módszerrel a változóknak:
PS C:\> Set-Variable -Name Nevem -Value "Soós Tibor" -Description "Ez az én nevem"
PS C:\> $nevem
Soós Tibor
De vajon hogyan olvashatjuk ki később ezt a magyarázó szöveget? Hát így nem:
PS C:\> $nevem.description
Ehhez a get-variable cmdletet kell használni:
PS C:\> (get-variable nevem).Description
Ez az én nevem
A get-variable kimeneteként nem maga a változó tartalma jön vissza, hanem egy PSVariable típusú objektum, aminek már kiolvasható a Description tulajdonsága is.
PS C:\> (get-variable nevem).gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSVariable System.Object
A korábban már mutatott Set-Variable cmdlethez hasonlóan a new-variable is használható új változók definiálásához, a két parancs között csak az a különbség, hogy a set-variable segítségével már meglevő változók tartalmát is meg lehet változtatni, a new-variable erre nem alkalmas:
PS C:\> $x = "körte"
PS C:\> New-Variable x -Value 55
New-Variable
: A variable with name 'x' already exists.
At line:1
char:13
+
New-Variable <<<< x -Value
55
+ CategoryInfo : ResourceExists: (x:String)
[New-Variable], Sess
ionStateException
+ FullyQualifiedErrorId :
VariableAlreadyExists,Microsoft.PowerShell.Comm
ands.NewVariableCommand
Ha meguntunk egy változót, akkor tartalmát törölhetjük is a Clear-Variable cmdlet segítségével. Ez különösen akkor fontos, ha például egy nagyméretű gyűjtemény kerül bele a változóba, ami aztán szükségtelenné válik. Ha nem töröljük, akkor az továbbra is foglalja a memóriát. Ez magát a változót nem szünteti meg, csak az értékét törli:
[29] PS I:\>$x = "alma"
[30] PS I:\>Get-Variable x
Name Value
---- -----
x alma
[31] PS I:\>Clear-Variable x
[32] PS I:\>Get-Variable x
Name Value
---- -----
x
[33] PS I:\>Remove-Variable x
[34] PS I:\>Get-Variable x
Get-Variable
: Cannot find a variable with name 'x'.
At line:1
char:13
+
Get-Variable <<<< x
+
CategoryInfo : ObjectNotFound:
(x:String) [Get-Variable], Item
NotFoundException
+ FullyQualifiedErrorId :
VariableNotFound,Microsoft.PowerShell.Commands.
GetVariableCommand
A [32]-es promptnál látjuk, hogy a Clear-Variable után az $x változóm még létezik, csak nincs értéke. A Remove-Variable után a [34]-es promptban viszont már nem létezik $x.
Megjegyzés
Változónévnek mindenféle csúnyaságot is használhatunk, de lehetőség szerint ne tegyünk ilyet, mert a szkriptünk, parancssorunk értelmezhetőségét nagyon megnehezíthetjük:
[37] PS I:\>$1 = 5
[38] PS I:\>$1
5
[39] PS I:\>$1+2
7
[40] PS I:\>${kód}="sor"
[41] PS I:\>"${kód}sor"
sorsor
[42] PS I:\>$$ = "Dollár"
[43] PS I:\>$$
Dollár
[44] PS I:\>$_a="bla"
[45] PS I:\>$_a
bla
A kapcsos zárójel a változó nevében különleges szerepet kap:
[80] PS C:\munka> $a = "ablak"
[81] PS C:\munka> ${a}
ablak
Látható, hogy bár a változó neve csak egy „a” betű, ennek ellenére a kapcsos zárójelben szerepeltetve is ugyanazt az eredményt kaptam. Így a kapcsos zárójelnek az a szerepe, hogy olyan változóneveket is használhassunk, amelyek olyan karaktereket is tartalmaznak, amelyek ott nem megengedettek:
[20] PS C:\> ${Ez egy nem szép nevű változó! Hanem csúnya. Bizony} = 1
[21] PS C:\> ${Ez egy nem szép nevű változó! Hanem csúnya. Bizony}
1
Ilyenkor a TAB kiegészítés úgy működik, hogy a $Ez után leütött TAB a teljes, kapcsos zárójeles neve írja ki.