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.