Articles

Alt du noen gang ønsket å vite om switch-setningen

  • 03/01/2021
  • 12 minutter å lese
    • s
    • c
    • x

som mange andre språk, har powershell kommandoer for å kontrollere flyten av kjøring i yourscripts. En av disse uttalelsene er switch-setningen, og I PowerShell tilbyr den funksjoner som ikke finnes på andre språk. I dag tar vi et dypt dykk inn i å jobbe med PowerShellswitch.

Merk

den opprinnelige versjonen av denne artikkelen dukket opp på bloggen skrevet av @ KevinMarquette. ThePowerShell teamet takk Kevin for å dele dette innholdet med oss. Vennligst sjekk ut hans blogg atPowerShellExplained.com.

if-setningen

en av de første setningene du lærer erif – setningen. Det lar deg utføre et skriptblokkhvis en setning er $true.

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

du kan ha mye mer komplisert logikk ved å bruke elseif og else setninger. Her er et eksempelhvor jeg har en numerisk verdi for ukedag, og jeg vil få navnet som en streng.

$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

det viser seg at dette er et vanlig mønster, og det er mange måter å håndtere dette på. En av dem er med en switch.

Switch statement

switch setningen lar deg gi en variabel og en liste over mulige verdier. Hvis verdienkamper variabelen, blir skriptblokken utført.

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

for dette eksemplet samsvarer verdien av $day med en av de numeriske verdiene, og det riktige navnet tilordnes til $result. Vi gjør bare en variabel oppgave i dette eksemplet, men Noen PowerShellcan utføres i disse skriptblokkene.

Tilordne til en variabel

Vi kan skrive det siste eksemplet på en annen måte.

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

vi plasserer verdien på PowerShell-rørledningen og tilordner den til $result. Du kan gjøre det samme med if og foreach – setningene.

Standard

Vi kan brukedefault søkeord for å identifisere hva som skal skje hvis det ikke er samsvar.

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

her returnerer vi verdien Unknown i standard tilfelle.

Strings

jeg var matchende tall i de siste eksemplene, men du kan også matche strenger.

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

jeg bestemte meg for ikke å pakke innComponentRole ogLocation kamper i sitater her for å markere thatthey ‘ re valgfritt. switch behandler dem som en streng i de fleste tilfeller.

Arrays

En av de kule funksjonene I PowerShell switch er måten den håndterer arrays. Hvis du gir enswitch en matrise, behandler den hvert element i den samlingen.

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

hvis du har gjentatte elementer i arrayet ditt, blir de matchet flere ganger av appropriatesection.

PSItem

du kan bruke$PSItem eller$_ for å referere til gjeldende element som ble behandlet. Når vi gjør asimple match,$PSItem er verdien som vi samsvarer med. Jeg skal utføre noen avanserte matchesin neste avsnitt der denne variabelen brukes.

Parametere

En unik funksjon I PowerShell switch er at den har en rekke bryterparametere somendre hvordan den utfører.

-CaseSensitive

matchene er ikke case-sensitive som standard. Hvis du trenger å være case-sensitive, kan du bruke -CaseSensitive. Dette kan brukes i kombinasjon med de andre bryterparametrene.

-Wildcard

vi kan aktivere wildcard-støtte med bryteren -wildcard. Dette bruker samme jokertegnlogikk som operatoren-like for å gjøre hvert treff.

$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

her behandler vi en melding og sender den ut på forskjellige strømmer basert på innholdet.

-Regex

bryteren setningen støtter regex kamper akkurat som det gjør jokertegn.

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

jeg har flere eksempler på å bruke regex i en annen artikkel jeg skrev: de mange måtene å bruke regex på.

-Fil

et lite kjent trekk ved switch-setningen er at den kan behandle en fil med parameteren -File. Du bruker -file med en bane til en fil i stedet for å gi den et variabelt uttrykk.

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

det fungerer akkurat som å behandle en matrise. I dette eksemplet kombinerer jeg det med jokertegn og bruker $PSItem. Dette vil behandle en loggfil og konvertere den til advarsel og errormessages avhengig av regex kamper.

Avanserte detaljer

Nå som du er klar over alle disse dokumenterte funksjonene, kan vi bruke dem i sammenheng med mer avansert behandling.

Uttrykk

switch kan være på et uttrykk i stedet for en variabel.

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

uansett hva uttrykket evaluerer til, er verdien som brukes for kampen.

Flere treff

du har kanskje allerede plukket opp dette, men en switch kan matche flere forhold. Dette er spesielt sant når du bruker -wildcard eller -regex treff. Du kan legge til samme tilstand multipletimes og alle av dem er utløst.

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

alle tre av disse uttalelsene er avfyrt. Dette viser at hver tilstand er sjekket (i rekkefølge). Thisholds sant for behandling av arrays der hvert element sjekker hver tilstand.

Fortsett

Normalt er det her jeg vil introduserebreak setningen, men det er bedre at vi lærer å brukecontinue først. Akkurat som med en foreach loop, continue fortsetter til neste element inthe samlingen eller avslutter switch hvis det ikke er flere elementer. Vi kan omskrive det siste eksempeletmed fortsette uttalelser slik at bare en setning utfører.

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

I Stedet for å matche alle tre elementene, blir den første matchet og bryteren fortsetter til neste verdi. Fordi det ikke er noen verdier igjen å behandle, går bryteren ut. Dette neste eksemplet viser hvordan et jokertegn kan matche flere elementer.

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

fordi en linje i inngangsfilen kan inneholde både ordet Error og Warning, vil vi bare at den første skal utføre og deretter fortsette å behandle filen.

Pause

A break setningen avslutter bryteren. Dette er den samme virkemåten som continue presenterer for enkeltverdier. Forskjellen vises når du behandler en matrise. break stopper all behandling i bryterenogcontinue flytter til neste 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

I dette tilfellet, hvis vi treffer noen linjer som starter med Error får vi en feil og bryteren stopper.Dette er hva som break uttalelse gjør for oss. Hvis vi finner Error inne i strengen og ikkebare i begynnelsen skriver vi det som en advarsel. Vi gjør det samme for Warning. Det er mulig at en linje kan ha både ordet Error og Warning, men vi trenger bare en toprocess. Dette er hvacontinue – setningen gjør for oss.

Bryt etiketter

switch setningen støtterbreak/continue etiketter akkurat somforeach.

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

jeg personlig ikke liker bruk av bryte etiketter, men jeg ønsket å peke dem ut fordi de ‘ reconfusing hvis du aldri har sett dem før. Når du har flereswitch ellerforeach erklæringersom er nestet, vil du kanskje bryte ut av mer enn det indre elementet. Du kan plassere en labelon a switch som kan være målet for din break.

Enum

PowerShell 5.0 ga oss enums og vi kan bruke dem i en bryter.

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

hvis du vil beholde alt som sterkt skrevet enums, kan du plassere dem i parentes.

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

parentesene er nødvendig her slik at bryteren ikke behandler verdien ::Location asa bokstavelig streng.

ScriptBlock

Vi kan bruke en scriptblock for å utføre evalueringen for en kamp om nødvendig.

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

dette legger til kompleksitet og kan gjøre switch vanskelig å lese. I de fleste tilfeller hvor du vil brukenoe som dette ville det være bedre å brukeif ogelseif uttalelser. Jeg ville vurdere usingthis hvis jeg allerede hadde en stor bryter på plass, og jeg trengte to elementer for å treffe samme evaluationblock.

en ting som jeg tror hjelper med lesbarhet er å plassere skriptblokken i parentes.

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

den utfører fortsatt på samme måte og gir en bedre visuell pause når du raskt ser på den.

Regex $matches

vi må besøke regex for å berøre noe som ikke er umiddelbart åpenbart. Bruken av regexpopulerer$matches variabelen. Jeg går inn i bruken av$matches mer når jeg snakker om mange måter å bruke regex på. Her er en rask prøve for å vise den i aksjon med navngitte kamper.

$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

du kan matche en $null verdi som ikke trenger å være standard.

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

samme gjelder for en tom streng.

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

Konstant uttrykk

Lee Dailey påpekte at Vi kan bruke en konstant$true uttrykk for å evaluere elementer.Tenk deg om vi har flere boolske kontroller som må skje.

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

dette er en ren måte å evaluere og iverksette tiltak på statusen til flere boolske felt. Thecool ting om dette er at du kan ha en kamp flip status for en verdi som ikke har beenevaluated ennå.

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

Innstilling $isEnabled til $true i dette eksemplet sørger du for at $isVisible også er satt til å$true. Så når $isVisible blir evaluert, blir dens scriptblock påkalt. Dette er en bitcounter-intuitiv, men er en smart bruk av mekanikken.

$switch automatisk variabel

når switch behandler verdiene, oppretter den en enumerator og kaller den $switch. Dette isan automatisk variabel opprettet Av PowerShell, og du kan manipulere den direkte.

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

dette gir deg resultatene av:

24

ved å flytte enumeratoren fremover, blir det neste elementet ikke behandlet av switch men du kan få tilgang til denne verdien direkte. Jeg vil kalle det galskap.

Andre mønstre

Hashtables

En av mine mest populære innlegg er den jeg gjorde på hashtables. En av brukstilfellene for en hashtable er å være et oppslagstabell. Det er en alternativ tilnærming til et vanlig mønster som enswitch – setning ofte adresserer.

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

hvis jeg bare bruker enswitchsom et oppslag, bruker jeg ofte enhashtablei stedet.

Enum

PowerShell 5.0 introduserte Enum og det er også et alternativ i dette tilfellet.

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

Vi kunne gå hele dagen og se på forskjellige måter å løse dette problemet på. Jeg ville bare forsikre meg om at du visste at du hadde alternativer.

Siste ord

switch-setningen er enkel på overflaten, men den tilbyr noen avanserte funksjoner som de fleste ikke skjønner er tilgjengelige. Strenger disse funksjonene sammen gjør dette til en kraftig funksjon. Jeg håper du lærte noe som du ikke hadde innsett før.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *