2008-08-03 17:33
Jedną z głównych zalet powłok tekstowych w rodzaju PowerShella jest to, że pozwalają one na łączenie ze sobą małych, elementarnych poleceń w jedno duże zadanie. Gdy odbywa się to na zasadzie przekazywania wyników jednego programu na wejście następnego, mówimy o potokowaniu (pipelining). Znawcy basha mogliby rzucić np. takim przykładem:
cat < program.cpp | grep int | wc --lines[/code]
w którym to najpierw odczytywana jest zawartość pliku (<kbd>cat</kbd>), wyszukiwane są wszystkie linijki zawierające ciąg "int" (<kbd>grep</kbd>) i liczona jest ich ilość (<kbd>wc</kbd>). Całkiem oczywiste, prawda? ;-)
W PowerShellu przetwarzanie potokowe jest o tyle lepsze niż w innych powłokach, że między poleceniami wymienia się nie tekst, a obiekty .NET-owe. Dobrze byłoby więc wiedzieć, jak należy pisać własne skrypty, aby mogły one działać w potokach. Na szczęście nie jest to specjalnie trudne; prezentuje to ten oto skrypt:
[csharp]# pokemonize.ps1
# Zmienia litery w tekście na losowo duże lub małe
begin
{
# Inicjujemy generator liczb losowych
$rand = New-Object Random
}
process
{
$str = $_.ToString()
$result = New-Object Text.StringBuilder
# Zmieniamy znaki
for ($i = 0; $i -lt $str.Length; ++$i)
{
if ($rand.NextDouble() -lt [float]0.5)
{ $newChar = [Char]::ToLower($str[$i]) }
else
{ $newChar = [Char]::ToUpper($str[$i]) }
$result.Append($newChar) | Out-Null
}
# Wyświetlamy przetworzony ciąg
$result.ToString()
}[/csharp]
Tym, co on robi, jest losowa zmiana wielkości liter w ciągu stanowiącym tekstową reprezentację obiektu (lub obiektów), jaki dostaje na wejściu. Jednym słowem, dokonuje jego <em>pokemonizacji</em>... Pewnie dla niektórych byłoby to przydatne, ale powiedzmy, że to tylko taki przykład ;P
Najważniejsze jest to, że podany skrypt działa dobrze na obiektach otrzymanych poprzez potok, czyli np. linijkach tekstu odczytanego z pliku poprzez <kbd>Get-Content</kbd>:
[code]Get-Content ./Plik.txt | . ./pokemonize.ps1 | Out-Host
Dla każdego takiego obiektu (tutaj: wiersza z pliku) wykonywany jest blok process
, w którym to ów obiekt jest reprezentowany jako zmienna $_. Można to sobie wyobrazić jako wnętrze pętli foreach
, przelatującej po wszystkich obiektach z wejścia skrypt. Dodatkowo możemy jeszcze określić bloki: begin
(uruchamiany na samym początku) i end
(na końcu). W nich powinniśmy umieścić ewentualny kod inicjalizujący i/lub kończący pracę skryptu.