jakiś czas temu pisałem o tym, jak powinno się/można przekazywać wartości via pipeline. krótki komentarz…

clue jest takie, że:

  • trzeba włączyć funkcje zaawansowane cmdletbinding()
  • użyć bloku ‘process {}’ dzięki czemu każdy element będzie automatycznie procesowany przez ten blok kodu za każdym razem po ‘wpadnięciu’ do potoku.
  • dzięki temu można usunąć ‘foreach’ bo blok ‘process’ i tak wykona się dla każdego elementu.

warto się sqpić nad konsekwencją tego faktu. tablice przekazywać na [co najmniej] dwa podstawowe sposoby – jako potok oraz jako parametr:

1..10|.\test-multiValue.ps1
.\test-multiValue.ps1 (1..10)

… ale po usunięciu ‘foreach’ ze skryptu, przestanie działać prawidłowo przekazanie przez zmienną wyliczaną…

aby przekonać się o tym, można uruchomić poniższy skrypt, na oba sposoby, różniący się od poprzedniego wpisu tylko weryfikacją czy element jest tablicą:

[cmdletbinding()]
param(
    [parameter(mandatory=$true,valueFromPipeline=$true,position=0)][string[]]$identities
)

begin {
    write-host 'begin'
    if($identities -is [System.Array]) { 
        write-host 'array'
    }
}

process {
        write-host 'jakis text, zeby pokazac, ze zostanie wyswietlony FOREACH element'
        write-host $identities
}

end {
    write-host 'end.'
}

reasumując

dla zachowania możliwości wykonania zarówno poprzez potok jak i przez zmienną, lepiej zostawić pętlę foreach – nic złego nie robi.

eN.

Spread the love

Comments (1)

  1. Odpowiedz

    Warto doprecyzować czemu tak się dzieje, pozwoli to świadomie używać funkcji zaawansowanych.
    Tak więc, przekazując do skryptu/funkcji poprzez potok, przekazujemy 10 tablic jednoelementowych które są przetwarzane przez blok process {}. Dlatego dopisanie pętlę foreach w blok proces{} nie robi różnicy bo przetwarza po jednym elemencie. Dodatkowo można zauważyć, że zmienne nie trafią do bloku Begin{}
    Natomiast przekazując jako parametr, to do bloku process{} trafia jedna tablica składająca się z 10 elementów. Dlatego blok Process{} wykonywany jest tylko raz i jeśli chcemy uzyskać efekt jak przy przekazaniu potokowym musimy zastosować pętlę.
    Nie można traktować tego jako błąd. Poniżej zmodyfikowany skrypt aby zobrazować to co opisałem.
    [cmdletbinding()]
    param(
    [parameter(mandatory=$true,valueFromPipeline=$true,position=0)][string[]]$identities
    )

    begin {
    if($identities)
    {
    “Blok Begin; $identities”
    }
    elseif(-not $identities)
    {
    “Blok Begin;Brak elementu”
    }
    elseif($identities.Count -gt 0)
    {
    “Blok Begin; Ilosc elementow $($identities.Count)”
    }
    }

    process {

    if($identities.Count -le 1)
    {
    “Blok Process; Ilosc elementow $($identities.Count)”
    }
    elseif($identities.Count -gt 1)
    {
    foreach($id in $identities)
    {
    “Blok Process; Foreach; Ilosc elementow $($id.Count)”
    }
    }
    }

    end {
    write-host ‘end.’
    }
     
    .\test-multiValue.ps1 (1..10)
    1..10 |.\test-multiValue.ps1

Zostaw komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Time limit is exhausted. Please reload CAPTCHA.