Csővezeték, futószalag (Pipeline)

A hagyományos shellekhez hasonlóan a PowerShellnek is fontos eleme a csővezeték  (pipeline ), azzal a lényeges különbséggel, hogy a PowerShell-féle csővezetékben komplett objektumok (illetve objektumreferenciák) közlekednek, így a csővezeték minden eleme megkapja az előtte álló parancs által generált teljes adathalmazt, függetlenül attól, hogy az adott kimenet hogyan jelenne meg a képernyőn.

De mi is az a csővezeték, és hogyan működik? Talán nem is szerencsés a csővezeték elnevezés, hiszen ha valamit beöntünk egy csővezeték elején, az általában változatlan formában bukkan fel a végén, a PowerShell-féle csővezeték lényege pedig éppen a benne utazó dolgok (objektumok) átalakítása, megfelelő formára hozása. Sokkal szemléletesebb, ha csövek helyett egy futószalagot képzelünk el, amelyen objektumok utaznak, a szalag mellett álló munkásaink (a cmdletek) pedig szorgalmasan elvégzik rajtuk a megfelelő átalakításokat, mindegyikük azt, amihez éppen ő ért a legjobban. Egyikük lefaragja és eldobja a fölösleget, a következő kiválogatja a hibás darabokat, egy másik kiválogatja, és szépen becsomagolja az egybetartozókat, stb. A szalag végén pedig mi megkapjuk a készterméket, ha ügyesek voltunk (vagyis a megfelelő munkásokat állítottuk a szalag mellé, és pontosan megmondtuk nekik, hogy mit kell csinálniuk), akkor éppen azt, és olyan formában, amire és ahogyan szükségünk volt.

A csövezhetőség azzal is jár, hogy az egyik cmdlet kimenete a következő cmdlet bemeneteként megy tovább, anélkül hogy nekünk az első kimenetet el kellene mentenünk változóba. Ezt a paraméterátadást a PowerShell helyettünk elvégzi. Ez - annak figyelembevételével - különösen praktikus, hogy a különböző cmdletek kimeneteként többfajta, előre nem biztos, hogy pontosan meghatározható típusú kimenet, általánosan gyűjtemény, azaz collection lehet.

Ráadásul, ha ilyen gyűjtemény a kimenet, akkor lehet, hogy annak első tagja hamar előáll. Ha ügyesen van megírva a következő csőszakasz helyén álló cmdlet, akkor az már a rendelkezésre álló első gyűjteményelemet el is kezdheti feldolgozni, sőt, akár tovább is adhatja az ő utána következő csőszakasznak. Ez jóval hatékonyabb feldolgozást tesz lehetővé memória-felhasználás tekintetében, hiszen nem kell bevárni az utolsó elem megérkezését és eltárolni az addigi elemeket.

Nézzünk egy nagyon egyszerű példát, a már többször alkalmazott get-member  cmdlet példáján. Látható, hogy a csőszakaszok csatlakozását a |  jel (Alt Gr + W) jelenti:

[4] PS C:\> "sztring" | get-member

 

 

   TypeName: System.String

 

Name             MemberType            Definition

----             ----------            ----------

Clone            Method                System.Object Clone()

CompareTo        Method                System.Int32 CompareTo(Object val...

Contains         Method                System.Boolean Contains(String va...

CopyTo           Method                System.Void CopyTo(Int32 sourceIn...

EndsWith         Method                System.Boolean EndsWith(String va...

Equals           Method                System.Boolean Equals(Object obj)...

...

A beírt „sztring” kimenete maga a „sztring”, ezt küldjük tovább a get-member cmdletnek, amely kilistázza a sztring objektum tagjait.

De vajon honnan tudja a PowerShell, hogy a get-member számos paramétere közül melyik legyen a csőből kieső kimenet?

Ehhez az adott cmdlet helpje (itt most kicsit megkurtítva) ad segítséget:

[5] PS C:\> get-help get-member -full

 

NAME

    Get-Member

 

SYNOPSIS

    Gets information about objects or collections of objects.

 

SYNTAX

    Get-Member [[-name] <string[]>] [-inputObject <psobject>] [-memberType

    {<AliasProperty> | <CodeProperty> | <Property> | <NoteProperty> | <Scri

    ptProperty> | <Properties> | <PropertySet> | <Method> | <CodeMethod> |

    <ScriptMethod> | <Methods> | <ParameterizedProperty> | <MemberSet> | <A

    ll>}] [-static] [<CommonParameters>]

 

 

DETAILED DESCRIPTION

    Gets information about the members of objects. Get-Member can accept in

...

 

PARAMETERS

    -name <string[]>

        Specifies the member names to retrieve information about.

 

        Required?                    false

        Position?                    1

        Default value                *

        Accept pipeline input?       false

        Accept wildcard characters?  true

 

    -inputObject <psobject>

        Specifies the objects to retrieve information about. Using this par

        ameter to provide input to Get-Member results in different output t

        han pipelining the same input. When you pipeline input to Get-Membe

        r, if the input is a container, the cmdlet returns information abou

        t each unique type of element in the container. If you provide the

        same input by using the InputObject parameter, the cmdlet returns i

        nformation about the container object itself. If you want to use pi

        pelining to retrieve information about a container, you must procee

        d the pipelined input by a comma (,). For example, if you informati

        on about processes stored in a variable named $process, you would t

        ype ,$process | get-member to retrieve information about the contai

        ner.

 

        Required?                    false

        Position?                    named

        Default value

        Accept pipeline input?       true (ByValue)

        Accept wildcard characters?  false

...

Tehát a cmdlet azon paramétere, amely fogadja a csővezetéken érkező adatot az általában „inputObject” névre hallgat, illetve a súgóban fel van tüntetve, hogy „Accept pipeline input? true”.

Látható tehát, hogy a get-member képes csőből adatokat feldolgozni, de vajon mi van akkor, ha egy cmdlet erre nem képes, vagy nincs is a mi céljainknak megfelelő cmdlet? Azaz a futószalag mellé nem tudunk beállítani egy kész, komplett gépet, hanem a gépet nekünk kell összerakni. Szerencsére erre is van lehetőség, számos ilyen „csőkezelő”, vagy „futószalag-melletti-gép-összerakó” cmdlet van, amelyekkel ezt meg lehet oldani. Most itt egyelőre csak kettőt vegyünk előre: a ForEach-Object  és a Where-Object cmdleteket.

A ForEach-Object a futószalag melletti üres gépház, a belsejét kapcsoszárójel-pár közé kell beírni. A következő példában a futószalagon érkező elemeket duplázza az általam összerakott gép:

[63] PS C:\> 1,8,3 | ForEach-Object {$_ * 2}

2

16

6

Mi van a gép belsejében? Egy olyan utasítássor, hogy: „Vedd az aktuális futószalagon érkező elemet, és szorozd meg kettővel!”. Az „aktuális futószalagon érkező elemet” a $_ furcsa nevű változó szimbolizálja. Ezzel a ForEach-Object belsejébe bekerül minden elem, azokon az előírt művelet végrehajtódik, majd az így módosított elem megy tovább a szalagon, jelen esetben itt vége is a szalagnak és az eredmény kihullott a képernyőre.

A másik fontos alapgép a futószalag mellett a szelektáló gép, ez csak azokat az elemeket engedi tovább, amelyek valamilyen általunk felállított kritériumot teljesítik. Ez a gép tehát magukat az elemeket nem módosítja, csak kicsit „megegyeli” azokat, mint a konzervgyárban az alul méretes almákat. Az ezt megvalósító cmdlet neve Where-Object . Nézzünk erre is példát:

[64] PS C:\> 15,2,11,5 | Where-Object {$_ -gt 10}

15

11

Itt azokat az elemeket engedjük csak tovább, amelyek teljesítik azt a megadott feltételt, hogy nagyobbak, mint 10.

Az 1.6.9 Pipe kezelése, filter c. fejezetben még részletesebben ismertetem a csövezést, hiszen ott majd mi magunk is írunk ilyen „csőképes” függvényt.



Word To HTML Converter