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 Component
Role
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.