PowerShell
Praca z potokiem PowerShell
Szukaj…
Wprowadzenie
PowerShell wprowadza model potokowania obiektów, który umożliwia wysyłanie całych obiektów w dół potoku do zużywających się komend lub (przynajmniej) danych wyjściowych. W przeciwieństwie do klasycznego potoku opartego na łańcuchach, informacje w obiektach potokowych nie muszą znajdować się w określonych pozycjach. Komendy mogą zadeklarować interakcję z obiektami z potoku jako danych wejściowych, a zwracane wartości są automatycznie przesyłane do potoku.
Składnia
- POCZĄTEK Pierwszy blok. Wykonany raz na początku. Dane wejściowe potoku mają tutaj wartość $ null, ponieważ nie zostały ustawione.
- PROCES Drugi blok. Wykonane dla każdego elementu potoku. Parametr potoku jest równy aktualnie przetwarzanemu elementowi.
- END Ostatni blok. Wykonany raz na końcu. Parametr potoku jest równy ostatniemu elementowi wejścia, ponieważ nie został zmieniony od czasu jego ustawienia.
Uwagi
W większości przypadków wejście potoku będzie tablicą obiektów. Chociaż zachowanie bloku PROCESS{}
może wydawać się podobne do bloku foreach{}
, pomijanie elementu w tablicy wymaga innego procesu.
Jeśli, podobnie jak w foreach{}
, użyłeś opcji continue
wewnątrz bloku PROCESS{}
, spowodowałoby to przerwanie potoku, pomijając wszystkie poniższe instrukcje, w tym blok END{}
. Zamiast tego użyj return
- zakończy tylko blok PROCESS{}
dla bieżącego elementu i przejdzie do następnego.
W niektórych przypadkach istnieje potrzeba wyprowadzenia wyniku funkcji z innym kodowaniem. Kodowanie danych wyjściowych CmdLets jest kontrolowane przez zmienną $OutputEncoding
. Jeśli dane wyjściowe są przeznaczone do umieszczenia w potoku do aplikacji rodzimych, dobrym pomysłem może być poprawienie kodowania, aby było zgodne z celem $OutputEncoding = [Console]::OutputEncoding
Dodatkowe referencje:
Artykuł na blogu zawierający więcej informacji na temat $OutputEncoding
https://blogs.msdn.microsoft.com/powershell/2006/12/11/outputencoding-to-the-rescue/
Pisanie funkcji z zaawansowanym cyklem życia
Ten przykład pokazuje, w jaki sposób funkcja może akceptować dane potokowe i wykonywać iteracje skutecznie.
Uwaga, że begin
i end
struktury funkcji podczas odbierania wiadomości jest opcjonalne, ale process
jest niezbędne przy korzystaniu ValueFromPipeline
lub ValueFromPipelineByPropertyName
.
function Write-FromPipeline{
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
$myInput
)
begin {
Write-Verbose -Message "Beginning Write-FromPipeline"
}
process {
Write-Output -InputObject $myInput
}
end {
Write-Verbose -Message "Ending Write-FromPipeline"
}
}
$foo = 'hello','world',1,2,3
$foo | Write-FromPipeline -Verbose
Wynik:
VERBOSE: Beginning Write-FromPipeline
hello
world
1
2
3
VERBOSE: Ending Write-FromPipeline
Podstawowe wsparcie rurociągów w funkcjach
To jest przykład funkcji z najprostszym możliwym wsparciem dla rurociągów.
Każda funkcja z obsługą potoku musi mieć co najmniej jeden parametr z ValueFromPipeline
ParameterAttribute ValueFromPipeline
lub ValueFromPipelineByPropertyName
, jak pokazano poniżej.
function Write-FromPipeline {
param(
[Parameter(ValueFromPipeline)] # This sets the ParameterAttribute
[String]$Input
)
Write-Host $Input
}
$foo = 'Hello World!'
$foo | Write-FromPipeline
Wynik:
Hello World!
Uwaga: W programie PowerShell 3.0 i nowszych obsługiwane są Domyślne wartości parametru ParameterAttributes. We wcześniejszych wersjach musisz podać wartość ValueFromPipeline=$true
.
Robocza koncepcja rurociągu
W serii potoków każda funkcja działa równolegle do innych, podobnie jak wątki równoległe. Pierwszy przetworzony obiekt jest przesyłany do następnego potoku, a następne przetwarzanie jest natychmiast wykonywane w innym wątku. To tłumaczy szybki wzrost prędkości w porównaniu ze standardowym ForEach
@( bigFile_1, bigFile_2, ..., bigFile_n) | Copy-File | Encrypt-File | Get-Md5
- krok - skopiuj pierwszy plik (w wątku
Copy-file
) - krok - skopiuj drugi plik (w wątku
Copy-file
) i jednocześnie Zaszyfruj pierwszyCopy-file
(wEncrypt-File
) - krok - skopiuj trzeci plik (w wątku
Copy-file
) i jednocześnie zaszyfruj drugi plik (wEncrypt-File
) i jednocześnieget-Md5
pierwszego (wGet-Md5
)