Formatowanie bez strat

formaOdkąd zacząłem korzystać z PowerShella zawsze starałem się pamiętać o podstawowej zasadzie: filtrowanie na lewo, formatowanie na prawo. Jedno wynika z tego, że im mniej danych pobierzemy ze źródła, tym mniej popłynie do nas z zewnętrznego źródła, cały proces gromadzenia danych ulegnie więc skróceniu. To jak wielka będzie to różnica zależeć będzie przede wszystkim od tego, jaki jest koszt pobrania danych i na ile koszt ten ogranicza ich wstępne filtrowanie. Stąd maja słabość do wszelkich filtrów LDAP, WQL-i, XPathów i innych. I tu raczej nigdy nic się nie zmieni – jeśli wiem jak filtrować u źródła, to nawet jeśli zysk jest znikomy tam właśnie będę się starał filtrować. Drugi jednak imperatyw wynika z ograniczenia, z którym przyzwyczaiłem się żyć: sformatowane obiekty nadają się jedynie do wyświetlania na ekranie, względnie do przekierowywania do pliku. Tak przynajmniej było dotychczas…

Formatujesz – demolujesz

PowerShell od samego początku oferował formatowanie, które osobiście uważam za doskonałe: zamiast oferować kilkanaście parametrów, dzięki którym można sformatować wyjście z danego polecenia (na ogół liczniejsze w przypadku poleceń wykorzystywanych często), w dodatku innych dla każdego ze znanych poleceń mamy po prostu grupę poleceń, które umożliwiają formatowanie wyników dowolnego polecenia. Korzyści są dwojakie. Przede wszystkim nie trzeba zaśmiecać pamięci grupą parametrów, których jedynym celem jest formatowanie wyjścia. Rzecz szalenie istotna, gdy polecenia w potoku operują na ciągach znaków, mniej istotne jeśli, tak jak w PowerShellu, komunikacja opiera się na obiektach i ich właściwościach. Po drugie sposób formatowania wyniku polecenia, które wykorzystywane jest rzadko, będzie identyczny jak ten, z którego skorzystamy w przypadku poleceń wykorzystywanych rzadziej. Rozdzielenie wyjścia od tego, jak wynik polecenia wygląda na ekranie (to co widzisz nie jest tym, co uzyskujesz) powoduje, że polecenia przeznaczone do formatowania mogły ograniczyć się do tego właśnie: formatowania. Miało to jednak negatywne konsekwencje. Raz sformatowane, obiekty na zawsze traciły swoją elastyczność i przejrzystość. Na wyjściu poleceń formatujących nadal uzyskujemy obiekty, nie mają one jednak nic wspólnego z obiektami wejściowymi. Łatwo to sprawdzić korzystając z polecenia Get-Member:

Get-Disk | Format-List | Get-Member | Select-Object -Unique -Property TypeName
<#
Output:
TypeName
--------
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
#>

Naturalną konsekwencją tego faktu jest konieczność usuwania poleceń formatujących za każdym razem, gdy wynik polecenia nie spełnia naszych oczekiwań i występuje konieczność przetworzenia zwróconych przez nie obiektów. Gramy z konsolą w swoistego ping-ponga:

# OK
Get-Process | Format-Wide -Column 3 -Property Path
# ??
Get-Process | Format-Wide -Column 3 -Property Path | Where Path -notlike 'c:\windows\*'
# OK... format...?
Get-Process | Where Path -notlike 'c:\windows\*'
# OK
Get-Process | Where Path -notlike 'c:\windows\*' | Format-Wide -Column 3 -Property Path

O ile przyjemniej pracowałoby się z poleceniami z grupy Format-*, gdyby nie powodowały uszkodzenia zwracanych obiektów…

Formatowanie bezstratne

Z pomocą znów służyć nam będzie Kirk i kolejny z jego modułów: FormatPx. Moduł ten, podobnie jak moduł HistoryPx o którym pisałem niedawno pobrać możemy z galerii, bądź z GitHuba. Podobnie jak to miało miejsce w przypadku wspomnianego modułu, konieczne będzie zainstalowanie modułu SnippetPx (jeśli go jeszcze nie posiadamy). W przypadku galerii moduł zostanie pobrany bez naszego udziału, jeśli jednak pobierzemy moduł z GitHuba musimy pamiętać o tym, by pobrać oba moduły.

Po zainstalowaniu i zaimportowaniu modułu FormatPx polecenia tradycyjnie wykorzystywane przez PowerShella do formatowania wyjścia i jego przekierowania (Format-* oraz Out-*) zostaną zastąpione przez ich odpowiedniki (Kirk definiuje je jako cmdlety zastępcze – podobne w sposobie działania do funkcji zastępczych, ale o wiele bardziej wydajne), które nie będą siać zniszczenia wśród przekazywanych do nich obiektów. Obiekt na wyjściu wyglądać będzie inaczej, ale działać będzie identycznie. Wracając do naszego przykładu z Get-Member – korzystając ze zmodyfikowanej wersji Format-List na wyjściu uzyskamy obiekty typu MSFT_Disk:

Import-Module -Name FormatPx
Get-Disk | Format-List | Get-Member | Select-Object -Unique -Property TypeName
<#
Output:
TypeName
--------
Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/Storage/MSFT_Disk
#>
view raw SaveFormat.ps1 hosted with ❤ by GitHub

Co ciekawe, informacja o formatowaniu nadal jest przechowywana. Jeśli więc zdecydujemy się sformatowane obiekty przefiltrować (tak, jak próbowaliśmy to uczynić w przypadku ścieżek do uruchomionych procesów) to wynik polecenia Where-Object nadal będzie prezentowany tak, jak obiekty bez dodatkowego filtrowania:

Get-Process | Format-Wide -Column 3 -Property Path | Where Path -notlike 'c:\windows\*'
<#
Format wide, 3 kolumny... bez procesów z c:\windows
#>
Get-Process | Format-Wide -Column 3 -Property Path | Where Path -notlike 'c:\windows\*' | Format-Wide -Column 5
<#
Domyślna właściwość System.Diagnostics.Process przy Format-Wide to Name....
Na wyjściu: 5 kolumn nazw procesów nie uruchomionych z c:\windows
#>

Możemy więc swobodnie formatować sformatowane, po tym jak już formatowaliśmy, wszystko bez straty informacji o początkowych obiektach. A także grupować, sortować i filtrować sformatowane obiekty… Może nie jest to zmiana tak rewolucyjna jak ta, którą oferuje HistoryPx – ale nadal moim zdaniem warto przyjrzeć się możliwościom tego modułu. Choćby po to, by nie musieć martwić się tym, w którym miejscu w "rurce" umieścić magiczną formułę Format-PoMojemu…. Winking smile

~ - autor: Bartek Bielawski w dniu 2 marca, 2017.

Jedna odpowiedź to “Formatowanie bez strat”

  1. Pomimo, że nie wszystko jest dla mnie jasne to z przyjemnością przeczytałam 🙂

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Połączenie z %s

 
%d blogerów lubi to: