SWITCH

A SWITCH  kulcsszóval nagyon bonyolult IF/ELSEIF/ELSE feltételrendszerek tudunk nagyon átláthatóan, egyszerűen megvalósítani. Sőt! Még akár bonyolultabb ForEach-Object vagy Where-Object cmdleteket is tudunk helyettesíteni ezzel úgy, hogy a szkriptünk sokkal átláthatóbb és egyszerűbb lesz. Nézzünk erre egy példát, először egy IF szerkezet kiváltására:

[46] PS C:\> $a = 1

[47] PS C:\> if($a -gt 10){"nagyobb mint 10"}elseif($a -gt 5) {"kisebbegyenl

ő 10, nagyobb 5"} else{"kisebbegyenlő 5"}

kisebbegyenlő 5

Ennek switch-et alkalmazó megfelelője:

[48] PS C:\> switch($a)

>> { {$a -gt 10} {"nagyobb mint 10"}

>>     {$a -gt 5} {"kisebbegyenlő 10, nagyobb 5"}

>>     default {"kisebbegyenlő 5"}

>> }

>> 

kisebbegyenlő 5

Vajon tényleg ekvivalens egymással? Nézzük meg, hogy mi van akkor, ha $a=15:

[49] PS C:\> $a = 15

[50] PS C:\> if($a -gt 10){"nagyobb mint 10"}elseif($a -gt 5){"kisebbegyenlő 10, nagyobb 5"}else{"kisebbegyenlő 5"}

nagyobb mint 10

Switch-csel:

[52] PS C:\> switch($a)

>> { {$a -gt 10} {"nagyobb mint 10"}

>>     {$a -gt 5} {"kisebbegyenlő 10, nagyobb 5"}

>>     default {"kisebbegyenlő 5"}

>> }

>> 

nagyobb mint 10

kisebbegyenlő 10, nagyobb 5

Azt láthatjuk itt, hogy a switch különböző sorai nem igazi ELSEIF módon működnek, azaz nem csak akkor adódik rájuk a vezérlés, ha a megelőző sorok nem adtak eredményt, hanem minden esetben. Ha ezt nem szeretnénk, akkor használjuk a BREAK  kulcsszót:

[53] PS C:\> switch($a)

>> { {$a -gt 10} {"nagyobb mint 10"; break}

>>     {$a -gt 5} {"kisebbegyenlő 10, nagyobb 5"; break}

>>     default {"kisebbegyenlő 5"}

>> }

>> 

nagyobb mint 10

Ez már ugyanazt a kimenetet adta, mint az IF-es megoldás. Tulajdonképpen a default ág előtti break felesleges, mert oda a vezérlés csak akkor kerül, ha egyik megelőző feltétel sem teljesül, de ha kiírjuk, akkor sem okoz ez semmilyen problémát.

A fenti példák talán még nem érzékeltetik eléggé a switch előnyét, hiszen itt csak egy háromtagú IF láncolatot helyettesítettem. Többtagú kifejezés esetén jobban látszódna a switch átláthatósága, bár így is, a legbeágyazottabb ELSE ág helyett sokkal szebben néz ki egy default  címke.

Még jobban kiviláglik a switch egyszerűsége, ha egyenlőségre vizsgálunk, hiszen ekkor nem kell külön az egyenlőség operátort sem használni:

[1] PS C:\> $a = 10

[2] PS C:\> switch($a){ 1 {"egy"} 2 {"kettő"} 3 {"három"} 10 {"tíz"} default {"egyéb"}}

tíz

De itt nem is ér véget a switch előnye, mert – ellentétben az IF-fel – a switch még gyűjteményeket is képes kezelni, így nagyon jó alternatívája lehet a ForEach-Object és a Where-Object cmdleteknek is. Például egy „ékezetlenítő” szkript csak ennyiből áll:

[42] PS C:\> $a = "öt új űrírás az ütvefúrógépen"

[43] PS C:\> $ofs="";"$(switch([char[]] $a){'á' {'a'} 'é' {'e'} 'í' {'i'} 'ó' {'o'} 'ö' {'o'} 'ő' {'o'} 'ú' {'u'} 'ü' {'u'} 'ű' {'u'} default {$_}})"

ot uj uriras az utvefurogepen

Itt a switch megkapja az $a sztringből képzett karaktertömböt ([char[]]), majd a sok karaktercserét megvalósító switch tag után visszakonvertálom a karaktersorozatot adó kimenetet (az egész kifejezés $()-ben) sztringgé (””), de úgy, hogy ne legyen elválasztó szóköz karakter a betűk között ($ofs=””).

Megjegyzés

Bár nem használtam a fenti példában explicit csövet, azaz a „|” csőjelet, de mégis hivatkozható a switch-ben a $_ változó.

–wildcard

És még itt sem ér véget a switch lehetőség-tára. Gyakran foglalkozunk szövegek vizsgálatával, így például ilyen jellegű kifejezések is gyakran szükségessé válnak:

[44] PS C:\> $a = "szöveg"

[45] PS C:\> switch ($a) {{$a -like "s*"} {"s-sel kezdődik"} {$a -like "z*"} {"z-vel kezdődik"}}

s-sel kezdődik

Ha ezt próbálnánk egyszerűbben írni, és kihagyjuk a „-like” operátort, akkor nem kapunk jó eredményt:

[46] PS C:\> switch($a){s* {"s-sel kezdődik"} z* {"z-vel kezdődik"}}

[47] PS C:\>

Hiszen ekkor a switch egyenlőséget vizsgált. Ha –like feltétel van mindenütt, akkor a switch –wildcard  kapcsolójával tudjuk az alaphelyzet szerinti egyenlőségvizsgálatot ‑like vizsgálattá alakítani:

[48] PS C:\> switch -wildcard ($a) {s* {"s-sel kezdődik"} z* {"z-vel kezdődik"}}

 

s-sel kezdődik

–regex

Szintén gyakori eset a szövegminták vizsgálata, mint ahogy erre már láttunk példát a 1.4.7   Regex (-match, -replace, -cmatch, -creplace) fejezetben. A switch erre is fel van készítve:

[3] PS C:\> $vizsgálandó="telefon: (30) 311-6867"

[4] PS C:\> switch -regex ($vizsgálandó)

>> {'\((\d{1,2})\)(-|\s)' {"Körzetszám: $($matches[1])"; break}

>> default {"Nincs körzetszám"}}

>> 

Körzetszám: 30

[5] PS C:\> $vizsgálandó = "Telefon: 123-4567"

[6] PS C:\> switch -regex ($vizsgálandó)

>> {'\((\d{1,2})\)(-|\s)' {"Körzetszám: $($matches[1])"; break}

>> default {"Nincs körzetszám"}}

>> 

Nincs körzetszám

A fenti példában zárójelek közti 1 vagy 2 számjegyből álló mintát keresek a vizsgálandó szövegben, amely mintát vagy szóköz, vagy kötőjel követ. Ha van ilyen, akkor a regex belső csoportképzésével kiadódó zárójelek közti számot adom vissza körzetszám gyanánt, egyébként kiíratom, hogy nincs körzetszám.

Sőt! Még a -casesensitive kapcsolóval kis-nagybetű érzékennyé is tehetjük:

PS C:\> switch -regex -casesensitive ("BC"){"C"{"kis c"}default{"nincs kis c"}}

kis c

PS C:\> switch -regex -casesensitive ("BC"){"c"{"kis c"}default{"nincs kis c"}}

nincs kis c

Ez a lehetőség természetesen a -wildcard üzemmód mellett is elérhető.

A $switch változó

Hasonlóan a ForEach kulcsszóhoz, a switch-nek is van belső változója, melynek $switch  a neve, és amelyet felhasználhatunk ciklus-jellegű működés megvalósításra:

[8] PS C:\> $Hosszú = "Vezetéknév: Soós

>> Keresztnév: Tibor

>> e-mail: soostibor@citromail.hu

>> Telefon: 30-3116867

>> Város: Budapest"

>> 

[9] PS C:\> $darabok = $Hosszú.Split()

[10] PS C:\> $darabok

Vezetéknév:

Soós

Keresztnév:

Tibor

e-mail:

soostibor@citromail.hu

Telefon:

30-3116867

Város:

Budapest

[12] PS C:\> switch($darabok) {

>> "Vezetéknév:" {[void] $switch.MoveNext(); $vez = $switch.Current}

>> "Keresztnév:" {[void] $switch.MoveNext(); $ker = $switch.Current}

>> "e-mail:" {[void] $switch.MoveNext(); $ema = $switch.Current}

>> "Telefon:" {[void] $switch.MoveNext(); $tel = $switch.Current}

>> "Város:" {[void] $switch.MoveNext(); $var = $switch.Current}

>> }

>> 

[13] PS C:\> $ker

Tibor

[14] PS C:\> $vez

Soós

Tehát ez a változó akkor használható igazából, ha egy gyűjteményt adunk át a switch-nek. Ekkor a gyűjtemény egyes tagjait a $switch változó az ő MoveNext() metódusával ciklus-szerűen tudja kezelni. Maga a switch pedig meg tudja vizsgálni az egyes elemeket és a vizsgálat eredményének függvényében különböző kódrészletek futhatnak le.

A fenti példában van egy hosszú sztringem, amiből ki szeretném szedni a nem címke jellegű adatokat, és ezeket be akarom tölteni a megfelelő változókba. Elsőként feldarabolom a sztringet a Split() metódussal.  Az így megszülető szavakból álló $darabok tömböt átadom a switch-nek. Ha a switch címkét talál (Vezetéknév:, Keresztnév:, stb.), akkor tovább lép a következő darabra és azt betölti a megfelelő változóba. Így minden adat pont  a helyére került.

–file

A switch képes közvetlenül fájlból is felszedni a szövegtömböt, amin aztán soronként a maga ciklusait lefutja. Vigyázni kell azonban ennél a felhasználási módnál, mert itt nincs lehetőségünk a kódolás meghatározására, így ha nem unicode formátumú a szövegfájl, akkor például ékezetes betűkre történő vizsgálat valószínű nem fog helyes eredményt adni.

Én magam sem tudok most hirtelen életszerű példával előállni, mindenesetre ideidézem az about_switch súgó oldalt a switch –file illusztrálására.

    switch [-regex|-wildcard|-exact][-casesensitive] -file filename

 

    followed by

 

        {

            "string"|number|variable|{ expression } { statementlist }

            default { statementlist }

        }



Word To HTML Converter