Articles

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ć ComponentRole 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ętliforeachcontinue 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 $truedo 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.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *