Articles

Everything you ever wanted to know about the switch statement

  • 03/01/2021
  • 12 minutes to read
  • s
  • C
  • X

monien muiden kielten tapaan powershellissa on komentoja, joilla ohjataan suoritusvirtaa yourscriptsin sisällä. Yksi näistä lausumista on switch statement ja Powershellissa se tarjoaa ominaisuuksia, joita ei löydy muilla kielillä. Tänään sukellamme syvälle työskentelyyn Powershellillaswitch.

Huomautus

tämän artikkelin alkuperäinen versio ilmestyi @Kevinmarquetten kirjoittamassa blogissa. ThePowerShell-tiimi kiittää Keviniä tämän sisällön jakamisesta kanssamme. Tutustu hänen blogiinsa atPowerShellExplained.com.

if: n lausuma

yksi ensimmäisistä opituista lausumista on if lausuma. Sen avulla voit suorittaa komentosarjan lohkof lauseke on $true.

if ( Test-Path $Path ){ Remove-Item $Path}

voit saada paljon monimutkaisemman logiikan käyttämällä elseif ja else lausekkeita. Tässä on esimerkki, jossa minulla on numeroarvo viikonpäivälle ja haluan saada nimen merkkijonona.

$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

käy ilmi, että kyseessä on yleinen kuvio ja siihen on monia keinoja. Yksi niistä on switch.

Kytkinlauseke

switch lauseke antaa muuttujan ja listan mahdollisista arvoista. Jos arvonmuuttuja muuttuja, sen scriptblock suoritetaan.

$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'

tässä esimerkissä $day vastaa yhtä numeerisista arvoista, jolloin oikea nimi on $result. Teemme vain muuttuva tehtävä tässä esimerkissä, mutta kaikki PowerShell voidaan suorittaa kyseisissä komentosarja lohkot.

Määritä muuttuja

voimme kirjoittaa viimeisen esimerkin toisella tavalla.

$result = switch ( $day ){ 0 { 'Sunday' } 1 { 'Monday' } 2 { 'Tuesday' } 3 { 'Wednesday' } 4 { 'Thursday' } 5 { 'Friday' } 6 { 'Saturday' }}

asetamme arvon PowerShell-putkistoon ja osoitamme sen $result. Saman asian voi tehdä if ja foreach lauseilla.

oletus

voimme käyttää default – hakusanaa tunnistaaksemme, mitä pitäisi tapahtua, jos osumaa ei ole.

$result = switch ( $day ){ 0 { 'Sunday' } # ... 6 { 'Saturday' } default { 'Unknown' }}

tässä palautetaan arvo Unknown oletustapauksessa.

Jouset

i vastasi numeroita noissa viimeisissä esimerkeissä, mutta voit myös sovittaa merkkijonoja.

$item = 'Role'switch ( $item ){ Component { 'is a component' } Role { 'is a role' } Location { 'is a location' }}
is a role

päätin olla paketoimatta ComponentRole ja Location täsmää lainausmerkeissä korostaakseen, että ne ovat valinnaisia. switch käsittelee niitä useimmiten jonona.

paneelit

yksi PowerShellin siisteistä ominaisuuksista switch on tapa, jolla se käsittelee ryhmiä. Jos annetaanswitch array, se käsittelee jokaisen alkuaineen kyseisessä kokoelmassa.

$roles = @('WEB','Database')switch ( $roles ) { 'Database' { 'Configure SQL' } 'WEB' { 'Configure IIS' } 'FileServer' { 'Configure Share' }}
Configure IISConfigure SQL

Jos joukossasi on toistuvia kohteita, ne sovitetaan useasti appropriatesektiolla.

PSItem

voit käyttää $PSItem tai $_ viitataksesi käsiteltyyn ajankohtaan. Kun teemme asimplanttiottelun, $PSItem on se arvo, joka vastaa meitä. Aion suorittaa joitakin kehittyneitä matches seuraavassa osassa, jossa tätä muuttujaa käytetään.

parametrit

PowerShellin ainutlaatuinen ominaisuus switch on se, että siinä on useita kytkinparametreja, jotka muuttavat sen toimintaa.

-tapaukset

ottelut eivät ole oletusarvoisesti kirjainherkkiä. Jos tarvitset kirjainkokoa, voit käyttää-CaseSensitive. Tätä voidaan käyttää yhdessä muiden kytkinparametrien kanssa.

-jokerimerkit

voimme ottaa jokerimerkkien tuen käyttöön -wildcard – kytkimellä. Tämä käyttää samaa jokerimerkin logiikkaa kuin-like operaattori tekee jokaisen ottelun.

$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

tässä käsitellään sanomaa ja lähetetään se sitten eri puroihin sisällön perusteella.

-Regex

switch-lauseke tukee regex-osumia aivan kuten se tukee jokerimerkkejä.

switch -Regex ( $message ){ '^Error' { Write-Error -Message $Message } '^Warning' { Write-Warning -Message $Message } default { Write-Information $message }}

minulla on lisää esimerkkejä Regexin käytöstä toisessa kirjoittamassani artikkelissa: the many ways to use regex.

-tiedosto

vähän tunnettu kytkinlauseen ominaisuus on, että se voi käsitellä tiedostoa -File – parametrilla. Käytät -file tiedoston polun kanssa sen sijaan, että antaisit sille muuttuvan lausekkeen.

switch -Wildcard -File $path{ 'Error*' { Write-Error -Message $PSItem } 'Warning*' { Write-Warning -Message $PSItem } default { Write-Output $PSItem }}

se toimii aivan kuten jonon käsittely. Tässä esimerkissä yhdistän sen jokerikorttien vastaavuuteen ja käytän $PSItem. Tämä käsittelisi lokitiedoston ja muuttaisi sen varoitus-ja errormessages riippuen regex ottelut.

lisätiedot

nyt kun olet tietoinen kaikista näistä dokumentoiduista ominaisuuksista, voimme käyttää niitä edistyneemmän käsittelyn yhteydessä.

lausekkeet

switch voivat olla muuttujan sijaan lausekkeella.

switch ( ( Get-Service | Where status -eq 'running' ).name ) {...}

riippumatta siitä, mihin lauseke Arvioi, on ottelulle käytetty arvo.

useita otteluita

olet saattanut jo poimia tämän, mutta switch voi vastata useita ehtoja. Tämä pätee erityisesti käytettäessä -wildcard tai -regex matcheja. Voit lisätä saman ehdon multipletimes ja ne kaikki käynnistyvät.

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

kaikki nämä kolme lausetta ovat potkut. Tämä osoittaa, että jokainen ehto tarkistetaan (järjestyksessä). Tämä pätee käsittelyyn taulukoita, joissa kukin kohde tarkistaa kunkin ehdon.

Jatka

normaalisti tässä ottaisin käyttöön break lausuman, mutta on parempi, että opettelemme käyttämään continue ensin. Aivan kuten foreach loop, continue jatkaa seuraavaan kokoelmaan tai poistuu switch jos kohteita ei enää ole. Voimme kirjoittaa viimeisen esimerkin jatkuvilla lausumilla niin, että vain yksi lausuma toteutuu.

switch ( 'Word' ){ 'word' { 'lower case word match' continue } 'Word' { 'mixed case word match' continue } 'WORD' { 'upper case word match' continue }}
lower case word match

sen sijaan, että kaikki kolme erää täsmäisivät, ensimmäinen täsmää ja vaihto jatkuu seuraavaan. Koska ei ole arvoja jäljellä käsitellä, kytkin poistuu. Tässä seuraavassa esimerkissä näytetään, miten jokerimerkki voisi vastata useita kohteita.

switch -Wildcard -File $path{ '*Error*' { Write-Error -Message $PSItem continue } '*Warning*' { Write-Warning -Message $PSItem continue } default { Write-Output $PSItem }}

koska syötetiedoston rivi voi sisältää sekä sanan Error että Warning, haluamme vain ensimmäisen suorittavan ja sitten jatkavan tiedoston käsittelyä.

Break

a break statement poistuu kytkimestä. Tämä on sama käyttäytyminen, jonka continue esittää yksiarvoisille. Ero näkyy käsiteltäessä array. break pysäyttää kaiken käsittelyn kytkimessä ja continue siirtyy seuraavaan kohteeseen.

$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

tässä tapauksessa, jos osumme johonkin linjaan, joka alkaa Error, niin saamme virheen ja kytkin pysähtyy.Tämän tuo break statement tekee meille. Jos löydämme Error merkkijonon sisältä eikä vasta alussa, kirjoitamme sen varoitukseksi. Teemme saman Warning. On mahdollista, että viivalla voisi olla sekä sana Error että Warning, mutta tarvitsemme vain yhden toprossin. Näin tekee continue lausunto.

Break labels

switch statement tukee break/continue labels aivan kuten foreach.

: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 } }}

itse en pidä taukoetikettien käytöstä, mutta halusin huomauttaa niistä, koska ne eivät sovi, jos niitä ei ole ennen nähnyt. Kun sinulla on useita switch tai foreach statements that are needed, saatat haluta murtautua ulos muustakin kuin sisimmästä eniten erästä. Voit asettaa labelon a switch, joka voi olla break.

Enum

PowerShell 5.0 antoi meille enumit ja voimme käyttää niitä kytkimessä.

enum Context { Component Role Location}$item = ::Roleswitch ( $item ){ Component { 'is a component' } Role { 'is a role' } Location { 'is a location' }}
is a role

Jos haluat pitää kaiken yhtä vahvasti tyypitettyinä enumeina, voit sijoittaa ne sulkeisiin.

switch ($item ){ (::Component) { 'is a component' } (::Role) { 'is a role' } (::Location) { 'is a location' }}

sulkeita tarvitaan tässä, jotta kytkin ei käsittele arvoa ::Location kirjaimellisena merkkijonona.

ScriptBlock

voimme tarvittaessa käyttää scriptblockia suorittaaksemme ottelun arvioinnin.

$age = 37switch ( $age ){ {$PSItem -le 18} { 'child' } {$PSItem -gt 18} { 'adult' }}
'adult'

tämä lisää monimutkaisuutta ja voi tehdä switch vaikealukuiseksi. Useimmissa tapauksissa, joissa käyttäisit jotain tällaista, olisi parempi käyttää if ja elseif lausumia. Harkitsisin tämän käyttämistä, jos minulla olisi jo suuri kytkin paikallaan ja tarvitsisin kaksi kohtaa osuakseni samaan arviointiryhmään.

yksi asia, joka mielestäni auttaa luettavuuteen, on laittaa scriptblock sulkeisiin.

switch ( $age ){ ({$PSItem -le 18}) { 'child' } ({$PSItem -gt 18}) { 'adult' }}

se suorittaa edelleen samalla tavalla ja antaa paremman visuaalisen tauon, kun sitä katsoo nopeasti.

Regex $matches

meidän täytyy palata regexiin koskettaaksemme jotain, mikä ei ole heti itsestään selvää. Regekspopuloi$matches muuttuja. Käyn kyllä $matches enemmän, kun puhun Regexin monista käyttötavoista. Tässä on nopea näyte näyttää sen toiminnassa nimetty ottelut.

$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

voit vastata $null arvoa, jonka ei tarvitse olla oletusarvo.

$value = $nullswitch ( $value ){ $null { 'Value is null' } default { 'value is not null' }}```OutputValue is null

sama pätee tyhjään merkkijonoon.

switch ( '' ){ '' { 'Value is empty' } default { 'value is a empty string' }}```OutputValue is empty

Vakioilmaisu

Lee Dailey huomautti, että voimme käyttää vakiota $true lauseketta arvioidaksemme kohteita.Kuvitelkaa, jos meillä on useita Boolen tarkastuksia, jotka on tehtävä.

$isVisible = $false$isEnabled = $true$isSecure = $trueswitch ( $true ){ $isEnabled { 'Do-Action' } $isVisible { 'Show-Animation' } $isSecure { 'Enable-AdminMenu' }}
Do-ActionEnabled-AdminMenu

Tämä on puhdas tapa arvioida ja ryhtyä toimenpiteisiin useiden Boolen kenttien tilaa. Thecool asia tässä on, että voit olla yksi ottelu kääntää tilan arvo, jota ei ole arvioitu vielä.

$isVisible = $false$isEnabled = $true$isAdmin = $falseswitch ( $true ){ $isEnabled { 'Do-Action' $isVisible = $true } $isVisible { 'Show-Animation' } $isAdmin { 'Enable-AdminMenu' }}
Do-ActionShow-Animation

asetus $isEnabled to $true tässä esimerkissä varmistetaan, että $isVisible on myös asetettu$true. Sitten kun $isVisible saa evaluoinnin, sen scriptblock vedotaan. Tämä on bitcounter-intuitiivinen, mutta on fiksu käyttö mekaniikka.

$switch automatic variable

kun switch käsittelee arvojaan, se luo enumeraattorin ja kutsuu sitä $switch. Tämä on PowerShellin luoma automaattinen muuttuja ja voit manipuloida sitä suoraan.

$a = 1, 2, 3, 4switch($a) { 1 { $switch.MoveNext(); $switch.Current } 3 { $switch.MoveNext(); $switch.Current }}

näin saadaan tulokset:

24

siirtämällä enumeraattoria eteenpäin seuraava kohde ei pääse switch, mutta kyseisen arvon voi saada suoraan. Sanoisin sitä hulluudeksi.

muut kuviot

hashtagit

yksi suosituimmista postauksistani on se, jonka tein hashtageilla. Yksihashtable käyttötapauksista on Hakutaulukko. Tämä on vaihtoehtoinen lähestymistapa yleiseen kaavaan, jotaswitch lausuma käsittelee usein.

$day = 3$lookup = @{ 0 = 'Sunday' 1 = 'Monday' 2 = 'Tuesday' 3 = 'Wednesday' 4 = 'Thursday' 5 = 'Friday' 6 = 'Saturday'}$lookup
Wednesday

jos käytän vain switch Hakuna, käytän usein hashtable sen sijaan.

Enum

PowerShell 5.0 esitteli Enum ja se on myös tässä tapauksessa vaihtoehto.

$day = 3enum DayOfTheWeek { Sunday Monday Tuesday Wednesday Thursday Friday Saturday}$day
Wednesday

voisimme mennä koko päivän miettien eri tapoja ratkaista tämä ongelma. Halusin vain varmistaa, että sinulla on vaihtoehtoja.

Loppusanat

kytkinlauseke on pinnalta yksinkertainen, mutta se tarjoaa joitain edistyneitä ominaisuuksia, joita useimmat ihmiset eivät tajua olevan saatavilla. Näiden ominaisuuksien yhdistäminen tekee tästä voimakkaan ominaisuuden. Toivon, että opit jotain, mitä et ollut tajunnut aiemmin.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *