Csőelemek kezelése

Nézzük a következő problémát: szeretnék egy olyan függvényt, ami minden fajta objektumnak veszi a nevét és ezt, valamint a nevének a hosszát kiírja. A trükk az lenne még, hogy szeretném, ha ez a függvény csövezhető is lehetne és hagyományos módon is átadható legyen neki bármilyen objektum. Sőt! Ha sztringet adok neki, akkor azt és annak hosszát írja ki.

„Fejletlen” függvénnyel valahogy így indulnék el:

function névhossz

{

    param ($name)

   

    begin {

        if($name) {

            if($name -is [string]) {$name | névhossz}

            else {$name.name | névhossz}

        }

    }

    process {

        if($_) {

            if($_ -is [string]) {"Név: $_, név hossza: $($_.length)" }

            else {"Név: $($_.name), név hossza: $($_.name.length)" }

        }

    }

}

Hát… Nem nagyon szép. Hiszen kétszer kell implementálni az egész logikáját, egyszer arra az esetre, ha hagyományosan paraméterezzük, ezt a begin szekcióban tettem meg. Másodszor meg a csövezéses használatra, ezt a process részben tettem meg. És még ezen belül is kétszer kell megvalósítani azt az esetet, amikor a paraméterként átadott objektumnak sztring és külön, amikor nem az.

Nézzük mindezt fejlett függvénnyel:

function adv-név

{

    param(

    [Parameter(

        Mandatory = $true,

        ValueFromPipeline = $true,

        ValueFromPipelineByPropertyName = $true

    )]

    [string]

    $name

    )

    process {

        "Név: $name, név hossza: $($name.length)"

    }

}

Hoppá!!!! Ez sokkal szebb! A lényegi rész a process szekcióban található, gyakorlatilag nagyon egyszerű. Mindazt, amit a „fejletlen” változatban nekem kellett megvalósítani azt most megteszi helyettem a PowerShell! Nézzük, hogyan?

A függvény paraméterének neve $name. Egyrészt kötelező ez a paraméter (Mandatory), ezt már megtárgyaltuk korábban. Másrészt fogad objektumot a csővezetékből (ValueFromPipeline = $true). Ez ahhoz kell, hogy ha a csőből sztringek jönnek, akkor így is engedélyezzük a $name paraméter feltöltését. Harmadrészt fogad ez a paraméter úgy is értéket a csőből, hogy nem magát az objektumot adjuk át neki, hanem ha az objektumnak is van name tulajdonsága, akkor ezt adjuk át a függvényünk name paramétereként (ValueFromPipelineByPropertyName = $true). Ezért fontos, hogy a függvényem paraméterének neve szintén name legyen.

Nézzük, hogyan fut:

[21] PS C:\> Get-ChildItem | adv-név

Név: Program Files, név hossza: 13

Név: Program Files (x86), név hossza: 19

Név: Users, név hossza: 5

Név: Windows, név hossza: 7

Név: fájl.txt, név hossza: 8

[22] PS C:\> "kakukk", "csirke" | adv-név

Név: kakukk, név hossza: 6

Név: csirke, név hossza: 6

[23] PS C:\> adv-név "kakukk"

Név: kakukk, név hossza: 6

[24] PS C:\> adv-név (Get-Item C:\fájl.txt)

Név: C:\fájl.txt, név hossza: 11

Mind a négy elvárt módon működött a függvényem.

Megjegyzés

A sztring egy nagyon gyakran használt típus, és emiatt (majdnem?) minden objektumnak van ToString() metódusa. Elvileg nem feltétlenül kellett volna alkalmazni a ValueFromPipelineByPropertyName = $true kitételt, mert enélkül automatikusan ez a ToString metódus került volna meghívásra paraméterátadáskor. De mégis érdemes külön ezt a paraméterátadási lehetőséget feltüntetni, mert jobb, kiszámíthatóbb eredményt ad. Nézzük ezt a processzek esetében a függvényem ValueFromPipelineByPropertyName = $false változatával:

PS C:\Users\Administrator> Get-Process | adv-név

Név: System.Diagnostics.Process (conhost), név hossza: 36

Név: System.Diagnostics.Process (conhost), név hossza: 36

Név: System.Diagnostics.Process (csrss), név hossza: 34

Név: System.Diagnostics.Process (csrss), név hossza: 34

Látható, hogy bár működik így is a függvényem, de nem az igazi eredményt adta, mivel a processz objektumoknál a ToString metódus nem csak a processz nevét adja vissza, hanem a típusát is. Ezzel szemben a függvényem eredeti változatában jó eredményt kapok:

PS C:\Users\Administrator> Get-Process | adv-név

Név: conhost, név hossza: 7

Név: conhost, név hossza: 7

Név: csrss, név hossza: 5

Név: csrss, név hossza: 5

Ezzel a lehetőséggel tehát nagyon elegáns, a paramétereket csővezetékből is fogadni képes függvényeket tudunk létrehozni. Így most a 1.8.2 Csővezeték feldolgozása (Foreach-Object) – újra fejezetben látott „Saját-foreachobject” függvényt már sokkal profibban, tömörebben is meg tudnánk írni.

Összefoglalásul, a fejlett függvényekben a csővezetékből érkező objektumok „igazi” paraméterhez való rendelését tudjuk nagyon elegánsan rábízni a PowerShell környezetre, ezzel szintén sok munkát spórolhatunk meg és nem utolsó sorban sokkal átláthatóbb, elegánsabb lesz a szkriptünk.



Word To HTML Converter