wszystko, co chcielibyście wiedzieć o instrukcji switch
- 03/01/2021
- 12 minut na przeczytanie
-
- s
- c
- x
podobnie jak wiele innych języków, PowerShell ma polecenia do kontrolowania przepływu wykonywania w skryptach. Jedną z tych instrukcji jest instrukcja switch i w PowerShell oferuje funkcje, których nie można znaleźć w innych językach. Dzisiaj przyjrzymy się pracy z Powershellemswitch
.
Uwaga
Oryginalna wersja tego artykułu pojawiła się na blogu napisanym przez @KevinMarquette. Zespół ThePowerShell dziękuje Kevinowi za udostępnienie nam tej treści. Zapraszam do zapoznania się z jego blogiem atPowerShellExplained.com.
Instrukcja if
jednym z pierwszych instrukcji, których się nauczysz, jest instrukcjaif
. Pozwala na wykonanie bloku skryptu jeśli instrukcja jest $true
.
if ( Test-Path $Path ){ Remove-Item $Path}
możesz mieć znacznie bardziej skomplikowaną logikę, używającelseif
Ielse
. Oto przykład, w którym mam wartość liczbową dla dnia tygodnia i chcę uzyskać nazwę jako ciąg znaków.
$day = 3if ( $day -eq 0 ) { $result = 'Sunday' }elseif ( $day -eq 1 ) { $result = 'Monday' }elseif ( $day -eq 2 ) { $result = 'Tuesday' }elseif ( $day -eq 3 ) { $result = 'Wednesday' }elseif ( $day -eq 4 ) { $result = 'Thursday' }elseif ( $day -eq 5 ) { $result = 'Friday' }elseif ( $day -eq 6 ) { $result = 'Saturday' }$result
Wednesday
okazuje się, że jest to wspólny wzorzec i istnieje wiele sposobów radzenia sobie z tym. Jednym z nich jest switch
.
Instrukcja Switch
Instrukcjaswitch
pozwala na podanie zmiennej i listy możliwych wartości. Jeżeli valuematches zmienna, wtedy zostanie wykonana jej blokada skryptu.
$day = 3switch ( $day ){ 0 { $result = 'Sunday' } 1 { $result = 'Monday' } 2 { $result = 'Tuesday' } 3 { $result = 'Wednesday' } 4 { $result = 'Thursday' } 5 { $result = 'Friday' } 6 { $result = 'Saturday' }}$result
'Wednesday'
w tym przykładzie wartość$day
pasuje do jednej z wartości liczbowych, wtedy poprawna nazwa jest przypisana do$result
. W tym przykładzie robimy tylko przypisanie zmiennych, ale każdy PowerShell może być wykonany w tych blokach skryptów.
przypisanie do zmiennej
ostatni przykład możemy zapisać w inny sposób.
$result = switch ( $day ){ 0 { 'Sunday' } 1 { 'Monday' } 2 { 'Tuesday' } 3 { 'Wednesday' } 4 { 'Thursday' } 5 { 'Friday' } 6 { 'Saturday' }}
umieszczamy wartość w potoku PowerShell i przypisujemy ją do$result
. Możesz to zrobić za pomocąif
Iforeach
.
domyślne
możemy użyć default
słowo kluczowe, aby określić, co powinno się zdarzyć, jeśli nie ma dopasowania.
$result = switch ( $day ){ 0 { 'Sunday' } # ... 6 { 'Saturday' } default { 'Unknown' }}
tutaj zwracamy wartośćUnknown
w domyślnym przypadku.
ciągi
w tych ostatnich przykładach pasowałem do liczb, ale można też dopasować ciągi.
$item = 'Role'switch ( $item ){ Component { 'is a component' } Role { 'is a role' } Location { 'is a location' }}
is a role
postanowiłem nie zawijać Component
Role
I Location
pasuje w cudzysłowie, aby podkreślić, że są opcjonalne. switch
traktuje je jako ciąg znaków w większości przypadków.
Tablice
jedną z fajnych funkcji PowerShell switch
jest sposób obsługi tablic. Jeśli podaszswitch
tablicę, przetwarza ona każdy element w tej kolekcji.
$roles = @('WEB','Database')switch ( $roles ) { 'Database' { 'Configure SQL' } 'WEB' { 'Configure IIS' } 'FileServer' { 'Configure Share' }}
Configure IISConfigure SQL
Jeśli masz powtarzające się elementy w tablicy, to są one dopasowywane wielokrotnie przez odpowiednie ustawienie.
PSItem
Możesz użyć $PSItem
lub $_
, aby odwołać się do bieżącego elementu, który został przetworzony. Gdy wykonujemy proste dopasowanie, $PSItem
jest wartością, którą dopasowujemy. Będę wykonywał zaawansowane dopasowania w następnej sekcji, gdzie ta zmienna jest używana.
parametry
unikalną cechą PowerShell switch
jest to, że ma wiele parametrów przełącznika, które zmieniają sposób działania.
-CaseSensitive
dopasowania domyślnie nie uwzględniają wielkości liter. Jeśli potrzebujesz rozróżniać wielkość liter, możesz użyć -CaseSensitive
. Można go używać w połączeniu z innymi parametrami przełącznika.
-Wildcard
możemy włączyć obsługę wildcard za pomocą przełącznika-wildcard
. Używa To tej samej logiki wieloznacznej, co operator-like
do każdego dopasowania.
$Message = 'Warning, out of disk space'switch -Wildcard ( $message ){ 'Error*' { Write-Error -Message $Message } 'Warning*' { Write-Warning -Message $Message } default { Write-Information $message }}
WARNING: Warning, out of disk space
tutaj przetwarzamy wiadomość, a następnie wysyłamy ją do różnych strumieni na podstawie zawartości.
-Regex
Instrukcja switch obsługuje dopasowania regex tak samo jak używa symboli wieloznacznych.
switch -Regex ( $message ){ '^Error' { Write-Error -Message $Message } '^Warning' { Write-Warning -Message $Message } default { Write-Information $message }}
mam więcej przykładów użycia wyrażenia regularnego w innym artykule, który napisałem: wiele sposobów korzystania z wyrażenia regularnego.
-plik
mało znaną cechą instrukcji switch jest to, że może ona przetwarzać Plik z parametrem-File
. Używasz -file
ze ścieżką do pliku zamiast nadawania mu wyrażenia zmiennej.
switch -Wildcard -File $path{ 'Error*' { Write-Error -Message $PSItem } 'Warning*' { Write-Warning -Message $PSItem } default { Write-Output $PSItem }}
działa tak jak przetwarzanie tablicy. W tym przykładzie łączę go z dopasowaniem symboli wieloznacznych i używam $PSItem
. To przetworzy plik dziennika i przekonwertuje go na ostrzeżenia i komunikaty błędów w zależności od dopasowań regex.
zaawansowane Szczegóły
teraz, gdy już wiesz o wszystkich tych udokumentowanych funkcjach, możemy ich użyć w kontekście bardziej zaawansowanego przetwarzania.
wyrażenia
switch
może być na wyrażeniu zamiast zmiennej.
switch ( ( Get-Service | Where status -eq 'running' ).name ) {...}
niezależnie od tego, do jakiego wyrażenia zostanie obliczone, jest to wartość użyta do dopasowania.
wiele dopasowań
być może już to zauważyłeś, ale switch
może pasować do wielu warunków. Jest to szczególnie prawdziwe, gdy używa się dopasowań-wildcard
lub-regex
. Możesz dodać ten sam warunek wielokrotnie i wszystkie z nich są wyzwalane.
switch ( 'Word' ){ 'word' { 'lower case word match' } 'Word' { 'mixed case word match' } 'WORD' { 'upper case word match' }}
lower case word matchmixed case word matchupper case word match
wszystkie trzy z tych instrukcji są uruchamiane. To pokazuje, że każdy warunek jest sprawdzany (w kolejności). To prawda dla przetwarzania tablic, gdzie każdy element sprawdza każdy warunek.
Kontynuuj
normalnie, to jest miejsce, gdzie chciałbym wprowadzićbreak
instrukcja, ale lepiej, że nauczymy się używaćcontinue
pierwszy. Podobnie jak w przypadku pętliforeach
continue
przechodzi do następnego elementu w kolekcji lub wychodzi zswitch
, jeśli nie ma więcej elementów. Możemy przepisać ten ostatni przykładz instrukcjami continue tak, że tylko jedna instrukcja zostanie wykonana.
switch ( 'Word' ){ 'word' { 'lower case word match' continue } 'Word' { 'mixed case word match' continue } 'WORD' { 'upper case word match' continue }}
lower case word match
zamiast pasować do wszystkich trzech elementów, pierwszy jest dopasowany, a przełącznik przechodzi do wartości next. Ponieważ nie ma już żadnych wartości do przetworzenia, przełącznik kończy działanie. Następny przykład pokazuje, jak wieloznaczna karta może pasować do wielu elementów.
switch -Wildcard -File $path{ '*Error*' { Write-Error -Message $PSItem continue } '*Warning*' { Write-Warning -Message $PSItem continue } default { Write-Output $PSItem }}
ponieważ wiersz w pliku wejściowym może zawierać zarówno słowoError
, jak iWarning
, chcemy, aby pierwszy z nich wykonał, a następnie kontynuował przetwarzanie pliku.
Break
a break
polecenie wychodzi z przełącznika. Jest to to samo zachowanie, którecontinue
prezentuje dla singlevalues. Różnica jest wyświetlana podczas przetwarzania tablicy. break
zatrzymuje przetwarzanie w przełączniku, a continue
przechodzi na następny element.
$Messages = @( 'Downloading update' 'Ran into errors downloading file' 'Error: out of disk space' 'Sending email' '...')switch -Wildcard ($Messages){ 'Error*' { Write-Error -Message $PSItem break } '*Error*' { Write-Warning -Message $PSItem continue } '*Warning*' { Write-Warning -Message $PSItem continue } default { Write-Output $PSItem }}
Downloading updateWARNING: Ran into errors downloading filewrite-error -message $PSItem : Error: out of disk space+ CategoryInfo : NotSpecified: (:) , WriteErrorException+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
w tym przypadku, jeśli trafimy w jakieś linie zaczynające się odError
wtedy otrzymamy błąd i przełącznik się zatrzyma.To jest to, co robi dla nasbreak
oświadczenie. Jeśli znajdziemy Error
wewnątrz łańcucha, a nie tylko na początku, zapisujemy go jako ostrzeżenie. To samo robimy dla Warning
. Możliwe jest, że linia może mieć zarówno słowo Error
, jak i Warning
, ale potrzebujemy tylko jednego toprocesu. Oto, co dla nas robicontinue
.
łamanie etykiet
switch
Instrukcja obsługujebreak/continue
etykiety podobnie jakforeach
.
:filelist foreach($path in $logs){ :logFile switch -Wildcard -File $path { 'Error*' { Write-Error -Message $PSItem break filelist } 'Warning*' { Write-Error -Message $PSItem break logFile } default { Write-Output $PSItem } }}
osobiście nie podoba mi się używanie etykiet break, ale chciałem je zwrócić uwagę, ponieważ nie są używane, jeśli nigdy wcześniej ich nie widziałeś. Jeśli masz wieleswitch
lubforeach
oświadczeń, które są zagnieżdżone, możesz chcieć wyrwać się z więcej niż wewnętrznego elementu most. Możesz umieścić etykietę switch
, która może być celem twojego .
Enum
PowerShell 5.0 dał nam enum i możemy ich używać w przełączniku.
enum Context { Component Role Location}$item = ::Roleswitch ( $item ){ Component { 'is a component' } Role { 'is a role' } Location { 'is a location' }}
is a role
Jeśli chcesz zachować wszystko jako mocno wpisane wyliczenia, możesz umieścić je w nawiasach.
switch ($item ){ (::Component) { 'is a component' } (::Role) { 'is a role' } (::Location) { 'is a location' }}
nawiasy są tutaj potrzebne, aby przełącznik nie traktował wartości::Location
Asa dosłowny ciąg znaków.
ScriptBlock
w razie potrzeby możemy użyć scriptblock do przeprowadzenia oceny dopasowania.
$age = 37switch ( $age ){ {$PSItem -le 18} { 'child' } {$PSItem -gt 18} { 'adult' }}
'adult'
To zwiększa złożoność i może sprawić, że Twójswitch
będzie trudny do odczytania. W większości przypadków, gdy używasz czegoś takiego, lepiej byłoby użyć instrukcjiif
Ielseif
. Rozważyłbym użycie tego, gdybym miał już duży przełącznik i potrzebowałem dwóch elementów, aby trafić w ten sam blok oceny.
jedną rzeczą, która moim zdaniem pomaga w czytelności, jest umieszczenie bloku skryptów w nawiasach.
switch ( $age ){ ({$PSItem -le 18}) { 'child' } ({$PSItem -gt 18}) { 'adult' }}
nadal wykonuje ten sam sposób i daje lepszą wizualną przerwę, gdy szybko się na nią patrzy.
Regex $pasuje
musimy ponownie odwiedzić regex, aby dotknąć czegoś, co nie jest od razu oczywiste. Użycie wyrażenia regexpopuluje zmienną$matches
. Wchodzę w użycie $matches
więcej, gdy mówię o wielu sposobach używania wyrażenia regularnego. Oto krótki przykład, aby pokazać go w akcji z nazwanymi meczami.
$message = 'my ssn is 123-23-3456 and credit card: 1234-5678-1234-5678'switch -regex ($message){ '(?<SSN>\d\d\d-\d\d-\d\d\d\d)' { Write-Warning "message contains a SSN: $($matches.SSN)" } '(?<CC>\d\d\d\d-\d\d\d\d-\d\d\d\d-\d\d\d\d)' { Write-Warning "message contains a credit card number: $($matches.CC)" } '(?<Phone>\d\d\d-\d\d\d-\d\d\d\d)' { Write-Warning "message contains a phone number: $($matches.Phone)" }}
WARNING: message may contain a SSN: 123-23-3456WARNING: message may contain a credit card number: 1234-5678-1234-5678
$null
możesz dopasować$null
wartość, która nie musi być wartością domyślną.
$value = $nullswitch ( $value ){ $null { 'Value is null' } default { 'value is not null' }}```OutputValue is null
to samo dotyczy pustego łańcucha.
switch ( '' ){ '' { 'Value is empty' } default { 'value is a empty string' }}```OutputValue is empty
wyrażenie stałe
Lee Dailey zwrócił uwagę, że możemy użyć wyrażenia stałego $true
do oceny elementów .Wyobraź sobie, że mamy kilka sprawdzeń logicznych, które muszą się zdarzyć.
$isVisible = $false$isEnabled = $true$isSecure = $trueswitch ( $true ){ $isEnabled { 'Do-Action' } $isVisible { 'Show-Animation' } $isSecure { 'Enable-AdminMenu' }}
Do-ActionEnabled-AdminMenu
jest to czysty sposób na ocenę i podjęcie działań na statusie kilku pól logicznych. Fajna rzecz w tym, że można mieć jeden mecz przerzucić status wartości, która nie została jeszcze oceniona.
$isVisible = $false$isEnabled = $true$isAdmin = $falseswitch ( $true ){ $isEnabled { 'Do-Action' $isVisible = $true } $isVisible { 'Show-Animation' } $isAdmin { 'Enable-AdminMenu' }}
Do-ActionShow-Animation
ustawienie$isEnabled
na$true
w tym przykładzie upewnia się, że$isVisible
jest również ustawione na$true
. Następnie, gdy$isVisible
zostanie oceniony, zostanie wywołany jego blok skryptów. Jest to bitcounter-intuicyjny, ale sprytne wykorzystanie mechaniki.
$Switch zmienna automatyczna
gdyswitch
przetwarza jej wartości, tworzy enumerator i wywołuje go$switch
. Jest to automatyczna zmienna tworzona przez PowerShell i można nią bezpośrednio manipulować.
$a = 1, 2, 3, 4switch($a) { 1 { $switch.MoveNext(); $switch.Current } 3 { $switch.MoveNext(); $switch.Current }}
to daje wyniki:
24
przesuwając licznik do przodu, następny element nie zostanie przetworzony przezswitch
, ale możesz uzyskać tę wartość bezpośrednio. Nazwałbym to szaleństwem.
inne wzorce
Hashtables
jednym z moich najpopularniejszych postów jest ten, który zrobiłem na hashtables. Jednym z przypadków użycia hashtable
ma być tabela wyszukiwania. Jest to alternatywne podejście do wspólnego wzorca, do którego często odnosi się polecenieswitch
.
$day = 3$lookup = @{ 0 = 'Sunday' 1 = 'Monday' 2 = 'Tuesday' 3 = 'Wednesday' 4 = 'Thursday' 5 = 'Friday' 6 = 'Saturday'}$lookup
Wednesday
Jeśli używam tylkoswitch
jako Wyszukiwania, często używamhashtable
.
Enum
PowerShell 5.0 wprowadziłEnum
I jest to również opcja w tym przypadku.
$day = 3enum DayOfTheWeek { Sunday Monday Tuesday Wednesday Thursday Friday Saturday}$day
Wednesday
możemy cały dzień szukać różnych sposobów na rozwiązanie tego problemu. Chciałem się tylko upewnić, że wiesz, że masz inne opcje.
Ostatnie słowa
Instrukcja switch jest z pozoru prosta, ale oferuje pewne zaawansowane funkcje, których większość ludzi nie zdaje sobie sprawy, że są dostępne. Połączenie tych funkcji sprawia, że jest to potężna funkcja. Mam nadzieję, że nauczyłeś się czegoś, czego wcześniej nie zdawałeś sobie sprawy.